为了完成POJ中的一题(spell checker),要写一个最长公共子序列的程序,居然突然全给忘了,楞是没有写出来,深深的鄙视自己一下。
这也是一道动态规划的典型题。
递归实现如下(POJ提交会超时,但是确实可以实现):
using namespace std; #define max( a ,b ) ((a)>(b)?(a):(b)) //最长公共子序列 int maxlen( char *a, char *b) { int len = 0; while( *a == *b && *a != '\0') { a++; b++; len++; } if( *a != '\0' && *b != '\0') return len + max( maxlen( a + 1, b), maxlen( a, b + 1) ); return len; } int main() { char *a = "abcdefg"; char *b = "bbcdfg"; cout << "maxlen(" << a << ", " << b << " ) = " << maxlen( a, b ) << endl; return 0; }下面这个程序用到了动态规划(所谓动态规划就是将一个问题分解成为子问题递归求解,并且将中间结果保存以避免重复计算,关键就是1.找边界,2.找状态转移公式)。此例乃动态规划的典型题。具体实现如下:
#include<iostream> using namespace std; #define MAX 1000 int ndata[ MAX ][ MAX ]; //最长公共子序列 /* 递推公式: if( i == 0 || j == 0 ) maxlen( i, j ) = 0; else if( s1[i] == s2[j]) maxlen( i, j) = maxlen( i - 1, j -1) + 1; else maxlen( i, j) = max( maxlen(i, j - 1 ), maxlen( i - 1, j)); */ int main() { char a[MAX]; char b[MAX]; int i , j; int nTemp; while( scanf("%s%s", a + 1, b + 1) > 0) { int nLength1 = strlen( a + 1 ); int nLength2 = strlen( b + 1 ); for ( i = 0; i <= nLength1; i++) ndata[i][0] = 0; for ( j = 0; j <= nLength2; j++) ndata[0][j] = 0; for( i = 1; i <= nLength1; i++ ) for( j = 1; j <= nLength2; j++ ) { if( a[i] == b[j] ) ndata[i][j] = ndata[i - 1][j - 1] + 1; else { if( ndata[i][j - 1] > ndata[i -1][j]) ndata[i][j] = ndata[i][j - 1]; else ndata[i][j] = ndata[i - 1][j]; } } printf("%d\n", ndata[ nLength1][nLength2]); } return 0; }