小记:看题意,我以为是求最长递增子序列,但是看sample又不对,于是去看了discuss,发现原来是lcs。。。
思路:lcs是经典的dp问题,最好自己动手,想出dp转移方程
dp[i][j] 表示 第一串的前i个字符和第二串的前j个字符 的最长公共子序列(lcs)的长度
那么状态转移方程即为:
dp[i][j] = a[i-1] == b[j-1]? dp[i-1][j-1]+1: max(dp[i-1][j], dp[i][j-1]); (a,b为两个字符串)
之所以是a[i-1] b[j-1]是因为字符串都是从0开始的
我之前的一个代码,预处理一个字符与另一串比较的结果,预处理错了,导致wa了2次
for(int i = 0; i < len2; ++i){
if(str1[0] == str2[i]){
dp[0][i] = 1;
}
else {
dp[0][i] = 0;
}
}
for(int i = 0; i < len1; ++i){
if(str1[i] == str2[0]){
dp[i][0] = 1;
}
else {
dp[i][0] = 0;
}
}
for(int i = 1; i < len1; ++i){
for(int j = 1; j < len2; ++j){
if(str1[i] == str2[j]){
dp[i][j] = dp[i-1][j-1] + 1;
}
else {
dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
}
}
}
printf("%d\n", dp[len1-1][len2-1]);
这个的问题,在于预处理,例如a和ab,答案输出为0,这就是原因
改了就好了
#include <iostream> #include <stdio.h> #include <string.h> #include <math.h> #include <stdlib.h> #include <map> #include <set> #include <vector> #include <stack> #include <queue> #include <algorithm> using namespace std; #define mst(a,b) memset(a,b,sizeof(a)) #define eps 10e-8 const int MAX_ = 510; const int N = 100010; const int INF = 0x7fffffff; int dp[MAX_][MAX_]; char str1[MAX_], str2[MAX_]; int len1, len2; int main(){ while(~scanf("%s%s", str1,str2)){ len1 = strlen(str1); len2 = strlen(str2); for(int i = 0; i < len2; ++i){ dp[0][i] = 0; } for(int i = 0; i < len1; ++i){ dp[i][0] = 0; } for(int i = 1; i <= len1; ++i){ for(int j = 1; j <= len2; ++j){ if(str1[i-1] == str2[j-1]){ dp[i][j] = dp[i-1][j-1] + 1; } else { dp[i][j] = max(dp[i-1][j], dp[i][j-1]); } } } printf("%d\n", dp[len1][len2]); } return 0; }
这样交上去对了,但是预处理明显没对dp[0][len]进行初始化,这肯定是测试数据没有测试到,所以最好加上