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 }

 

posted @ 2021-07-09 15:59  永远是个小孩子  阅读(46)  评论(0编辑  收藏  举报