http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=114&page=show_problem&problem=1346
题目大意:
就是输入两个字符序列,输出两个序列的最长公共子序列(注意序列跟串的区别)。
题目类型:
经典dp /LCS
分析:
就是 最长公共子序列(LCS)的问题。d[i][j]表示a[i]之前、b[j]之前(含端点)的序列的最大子序列长度,
则状态转移方程:di,j = { di-1,j-1+1, 当a[i]=b[j]; max{di,j-1, di-1,j}, 当a[i]≠b[j]; }。
原问题的解就是 d(len(a)-1, len(b)-1) 了;
注:此题又很恶心,题目描述中没有说输入中有没有空格,结果用scanf WA了,换成gets 当场A了。注意咯。
总结:注意用scanf 读串的时候要小心, 注意与gets的区别!
代码:
#include<cstdio> #include<cstring> using namespace std; #define MAXN 1005 char a[MAXN], b[MAXN]; int d[MAXN][MAXN], vis[MAXN][MAXN]; int lcs(int i, int j) { if(i == -1 || j == -1) return 0; //停止条件 if(vis[i][j]) return d[i][j]; vis[i][j] = 1; if(a[i] == b[j]) return d[i][j] = lcs(i-1, j-1)+1; else return d[i][j] = lcs(i-1, j)>lcs(i, j-1)? lcs(i-1, j): lcs(i, j-1); } int main() { //while(scanf("%s%s", &a, &b) != EOF) //scanf遇空格停止。 while(gets(a) && gets(b)) //gets()的返回值是读入的字符串,如果错误返回NULL. { memset(vis, 0, sizeof(vis)); printf("%d/n", lcs(strlen(a)-1, strlen(b)-1)); } }