abcfbc abfcab programming contest abcd mnp
4 2 0
最长公共子序列,想了老半天都没想出状态方程~
它的原理是这样的~
最长公共子序列问题具有最优子结构性质
设
X = { x1 , ... , xm }
Y = { y1 , ... , yn }
及它们的最长子序列
Z = { z1 , ... , zk }
则
1、若 xm = yn , 则 zk = xm = yn,且Z[k-1] 是 X[m-1] 和 Y[n-1] 的最长公共子序列
2、若 xm != yn ,且 zk != xm , 则 Z 是 X[m-1] 和 Y 的最长公共子序列
3、若 xm != yn , 且 zk != yn , 则 Z 是 Y[n-1] 和 X 的最长公共子序列
由性质导出子问题的递归结构
当 i = 0 , j = 0 时 , c[i][j] = 0
当 i , j > 0 ; xi = yi 时 , c[i][j] = c[i-1][j-1] + 1
当 i , j > 0 ; xi != yi 时 , c[i][j] = max { c[i][j-1] , c[i-1][j] }
注意边界,两个串的下标都是从1开始的,因为递归时是以0为结束标志的~
dp[i][j] 表示的是 表示长度为i的字符串和长度为j的字符串的最大公共子串的长度
code:
#include<iostream> #include<string.h> using namespace std; char str1[1005]; char str2[1005]; int dp[1005][1005]; int main() { while(scanf("%s %s",str1+1,str2+1)!=EOF) { memset(dp,0,sizeof(dp));这一步就已经初始化边界了~ dp[0][j:1->len2]=0; // memset(str1,0,sizeof(str1));//脑袋抽抽了 刚输进去就给清了~ // memset(str2,0,sizeof(str2)); int len1=strlen(str1+1),len2=strlen(str2+1); 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]); } cout<<dp[len1][len2]<<endl; } return 0; }