题目来源:http://noi.openjudge.cn/ch0206/1808/
1808:公共子序列
总时间限制: 1000ms 内存限制: 65536kB
描述
我们称序列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
-----------------------------------------------------
解题思路
二维动态规划: dp[i][j]表示s1[i:s1.end())与s2[j:s2.end())的公共子串
实现时用两个一维数组dp1和dp分别代表dp[i][j]和dp[i+1][j]以节省内存
-----------------------------------------------------
代码
//1808:公共子序列 //总时间限制: 1000ms 内存限制: 65536kB //描述 //我们称序列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 // 动态规划: dp[i][j]表示s1[i:s1.end())与s2[j:s2.end())的公共子串 #include<fstream> #include<iostream> #include<string> using namespace std; int main() { #ifndef ONLINE_JUDGE ifstream fin("0206_1808.txt"); string s1,s2; int n1,n2,i,j; while(fin >> s1 >> s2) { /*int dp[201][201] = {}; n1 = s1.size(); n2 = s2.size(); if (n1==0 || n2==0) { cout << 0 << endl; continue; } dp[n1-1][n2] = 0; for (i=n1-1; i>=0; i--) { for (j=n2-1; j>=0; j--) { if (s1.at(i)==s2.at(j)) { dp[i][j] = max(dp[i][j+1]+1,dp[i+1][j]); } else { dp[i][j] = max(dp[i][j+1],dp[i+1][j]); } } } cout << dp[0][0] << endl;*/ int dp[201] = {}; // 模拟dp[i+1][j] int dp1[201] = {}; // 模拟dp[i][j] n1 = s1.size(); n2 = s2.size(); if (n1==0 || n2==0) { cout << 0 << endl; continue; } dp[n2] = 0; for (i=n1-1; i>=0; i--) { for (j=n2-1; j>=0; j--) { if (s1.at(i)==s2.at(j)) { dp1[j] = dp[j+1]+1; } else { dp1[j] = max(dp1[j+1],dp[j]); } } for (j=n2-1; j>=0; j--) { dp[j] = dp1[j]; } } cout << dp1[0] << endl; } fin.close(); return 0; #endif #ifdef ONLINE_JUDGE string s1,s2; int n1,n2,i,j; while(cin >> s1 >> s2) { /*int dp[201][201] = {}; n1 = s1.size(); n2 = s2.size(); if (n1==0 || n2==0) { cout << 0 << endl; continue; } dp[n1-1][n2] = 0; for (i=n1-1; i>=0; i--) { for (j=n2-1; j>=0; j--) { if (s1.at(i)==s2.at(j)) { dp[i][j] = max(dp[i][j+1]+1,dp[i+1][j]); } else { dp[i][j] = max(dp[i][j+1],dp[i+1][j]); } } } cout << dp[0][0] << endl;*/ int dp[300] = {}; // 模拟dp[i+1][j] int dp1[300] = {}; // 模拟dp[i][j] n1 = s1.size(); n2 = s2.size(); if (n1==0 || n2==0) { cout << 0 << endl; continue; } dp[n2] = 0; for (i=n1-1; i>=0; i--) { for (j=n2-1; j>=0; j--) { if (s1.at(i)==s2.at(j)) { dp1[j] = dp[j+1]+1; } else { dp1[j] = max(dp1[j+1],dp[j]); } } for (j=n2-1; j>=0; j--) { dp[j] = dp1[j]; } } cout << dp1[0] << endl; } #endif }