2806:公共子序列
总时间限制:
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
来源
翻译自Southeastern Europe 2003的试题
还是一道动态规划问题,又有了新的发现!!!!
#include<iostream> #include<string.h> using namespace std; char a[202],b[202]; int d[202][202]={0}; int lena,lenb; int maxx(int aa,int bb) { return aa>bb?aa:bb; } void solve(int sa,int sb) { for (int i=1;i<=sa;i++) for (int j=1;j<=sb;j++) { if (a[i-1]==b[j-1]) d[i][j]=d[i-1][j-1]+1; else d[i][j]=maxx(d[i-1][j],d[i][j-1]); } } int main() { while(cin>>a>>b) { lena=strlen(a); lenb=strlen(b); for (int i=0;i<=lena;i++) d[i][0]=0; for (int i=0;i<=lenb;i++) d[0][i]=0; solve(lena,lenb); cout<<d[lena][lenb]<<endl; } return 0; }
再次写到这道题,还是出现了一些问题,(1)d[0][]和d[][0]都应该是0,而字符串的输入时a[0],b[0]却并不代表着无字符,这是就需要将d[][]的整体后移一位,即d[1][1]代表的时a[0]和b[0]匹配的结果,那么在solve函数中的转移方程中的if语句的条件就该应该是a[i-1]==b[j-1] 而且for循环的最大为字符串的长度且从1开始。这里是容易混的地方。 于是最后的结果就是存在了d[lena][lenb]中。
由于动态规划的问题常常要用到max和min函数,而VS中却把这两个函数弄成了宏就是不能自己写函数名也是max或者min的函数,而且每次都写很麻烦,max和min函数在标准文件<algorithm>中,以后就不用每次都写了。 ~~~~~~~~舒服。
18-9-8.