2806:最长公共子序列,考点:动态规划
原题:http://bailian.openjudge.cn/practice/2806/
描述
我们称序列Z = < z1, z2, ..., zk >是序列X = < x1, x2, ..., xm >的子序列当且仅当存在 严格上升 的序列< i1, i2, ..., ik >,使得对j = 1, 2, ... ,k, 有xij = zj。比如Z = < a, b, f, c > 是X = < a, b, c, f, b, c >的子序列。
现在给出两个序列X和Y,你的任务是找到X和Y的最大公共子序列,也就是说要找到一个最长的序列Z,使得Z既是X的子序列也是Y的子序列。
输入
输入包括多组测试数据。每组数据包括一行,给出两个长度不超过200的字符串,表示两个序列。两个字符串之间由若干个空格隔开。
输出
对每组输入数据,输出一行,给出两个序列的最大公共子序列的长度。
样例输入
abcfbc abfcab
programming contest
abcd mnp
样例输出
4 2 0
解法
思路:动态规划,记忆性递归
边界条件:只有一个字符的时候
状态转移方程:maxlen(i,j)
如果a字符串的第i个字符和第j个字符相等,maxlen(i,j)=1+maxlen(i-1,j-1)
如果a字符串的第i个字符和第j个字符不相等,maxlen(i,j)=max(maxlen(i-1,j),maxlen(i,j-1))
1 #include <iostream> 2 #include <cstring> 3 #include <string> 4 #include <algorithm> 5 using namespace std; 6 int dp[205][205]; 7 string a, b; 8 int maxlen(int i, int j) { 9 if (dp[i][j] != -1) 10 return dp[i][j]; 11 if (i == 0 && j == 0) { 12 if (a[i] == b[j]) 13 dp[i][j] = 1; 14 else 15 dp[i][j] = 0; 16 return dp[i][j]; 17 } 18 else if (i == 0) { 19 dp[i][j] = 0; 20 for (int k = 0; k <= j; k++) { 21 if (a[i] == b[k]) { 22 dp[i][j] = 1; 23 break; 24 } 25 } 26 return dp[i][j]; 27 } 28 else if (j == 0) { 29 dp[i][j] = 0; 30 for (int k = 0; k <= i; k++) { 31 if (a[k] == b[j]) { 32 dp[i][j] = 1; 33 break; 34 } 35 } 36 return dp[i][j]; 37 } 38 else { 39 if (a[i] == b[j]) 40 dp[i][j] = 1 + maxlen(i - 1, j - 1); 41 else 42 dp[i][j] = max(maxlen(i - 1, j), maxlen(i, j - 1)); 43 return dp[i][j]; 44 } 45 } 46 int main() { 47 while (cin >> a >> b) { 48 memset(dp, -1, sizeof(dp)); 49 cout << maxlen(a.length() - 1, b.length() - 1) << endl; 50 } 51 return 0; 52 }
由于求的时候只用到i-1,j-1之类,所以也可以从上向下递推,代码如下
1 #include <iostream> 2 #include <cstring> 3 #include <string> 4 using namespace std; 5 string a, b; 6 int maxLen[1000][1000]; 7 int main() { 8 while (cin >> a >> b) { 9 int length1 = a.length(); 10 int length2 = b.length(); 11 int nTmp; 12 int i, j; 13 for (i = 0; i <= length1; i++) 14 maxLen[i][0] = 0; 15 for (j = 0; j <= length2; j++) 16 maxLen[0][j] = 0; 17 for (i = 1; i <= length1; i++) { 18 for (j = 1; j <= length2; j++) { 19 if (a[i - 1] == b[j - 1]) 20 maxLen[i][j] = maxLen[i - 1][j - 1] + 1; 21 else 22 maxLen[i][j] = max(maxLen[i][j - 1], 23 maxLen[i - 1][j]); 24 } 25 } 26 cout << maxLen[length1][length2] << endl; 27 } 28 return 0; 29 }