题目来源: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
}