http://acm.hdu.edu.cn/showproblem.php?pid=1159
最长公共子序列问题具有最优子结构性质
设
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的字符串的最大公共子串的长度
分析:
#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; 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; }
另:
#include<iostream> #include<cstring> using namespace std; int max(int a,int b) { return a>b?a:b; } int main() { int i,j,dp[500][500]; string s1,s2; while(cin>>s1>>s2) { memset(dp,0,sizeof(dp)); for(i=1;i<=s1.size();i++) { for(j=1;j<=s2.size();j++) { if(s1[i-1]==s2[j-1])dp[i][j]=dp[i-1][j-1]+1; else dp[i][j]=max(dp[i-1][j],dp[i][j-1]); } } cout<<dp[s1.size()][s2.size()]<<endl; } return 0; }