最长公共子序列可以用在下面的问题时:给你一个字符串,请问最少还需要添加多少个字符就可以让它编程一个回文串?
解法:ans=strlen(原串)-LCS(原串,反串);
Sample Input
abcfbc abfcab programming contest abcd mnp
Sample Output
4 2 0
代码:
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> #include <math.h> #include <iostream> #include <string> #include <algorithm> using namespace std; char s[10100], t[10100]; int dp[10100][10100]; //dp[i+1][j+1]:表示序列s的前i个和序列t的前j个的最长公共子序列 //因为字符串从0下标开始存储的 dp[][]数组的0行 0列都被初始化为0 //比如说s[0]=t[0] 就会推出dp[0+1][0+1]=dp[0][0]+1=1 //dp[1][1]=1 也就是s的前1个和t的前1个序列中最长序列为1 int LCS() { int i, j; int len1=strlen(s); int len2=strlen(t); for(i=0; i<len1; i++) dp[i][0]=0; for(i=0; i<len2; i++) dp[0][i]=0; for(i=0; i<len1; i++){ for(j=0; j<len2; j++){ if(s[i]==t[j]) dp[i+1][j+1]=dp[i][j]+1; else dp[i+1][j+1]=max(dp[i+1][j], dp[i][j+1]); } } return dp[len1][len2]; } int main() { while(scanf("%s", s)!=EOF){ scanf("%s", t); int ans=LCS(); printf("%d ", ans ); } return 0; }
现在我修改了字符串开始存储的位置,这样:scanf("%s", s+1); 从下标1开始存储,注意 正确的 len=strlen(s+1);
代码:
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> #include <math.h> #include <iostream> #include <string> #include <algorithm> using namespace std; char s[10100], t[10100]; int dp[10100][10100]; //dp[i+1][j+1]:表示序列s的前i个和序列t的前j个的最长公共子序列 //因为字符串从0下标开始存储的 dp[][]数组的0行 0列都被初始化为0 //比如说s[0]=t[0] 就会推出dp[0+1][0+1]=dp[0][0]+1=1 //dp[1][1]=1 也就是s的前1个和t的前1个序列中最长序列为1 int LCS() { int i, j; int len1=strlen(s+1); int len2=strlen(t+1); for(i=0; i<=len1; i++) dp[i][0]=0; for(i=0; i<=len2; i++) dp[0][i]=0; for(i=1; i<=len1; i++){ for(j=1; j<=len2; j++){ if(s[i]==t[j]) dp[i][j]=dp[i-1][j-1]+1; else dp[i][j]=max(dp[i-1][j], dp[i][j-1]); } } return dp[len1][len2]; } int main() { while(scanf("%s", s+1)!=EOF){ scanf("%s", t+1); int ans=LCS(); printf("%d ", ans ); } return 0; }