问题来源:刘汝佳《算法竞赛入门经典--训练指南》 P60 问题7:
问题描述:给两个子序列A和B,求长度最大的公共子序列。比如1,5,2,6,8,和2,3,5,6,9,8,4的最长公共子序列为5,6,8另一个解是2,6,8)。
分析:设dp[i][j]为A1,A2,...,Ai和B1,B2,...,Bn的LCS长度,则状态转移方程为:
1 if(A[i]==B[i]) 2 d[i][j] = d[i-1][j-1]+1; 3 else 4 d[i][j] = Max{d[i-1][j],d[i][j-1]};
时间复杂度为O(n*m);其中空间可用滚动数组优化。
例题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1159
例题:hdu 1159
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 25784 Accepted Submission(s): 11428
1 #include "stdio.h" 2 #include "string.h" 3 #define N 1005 4 5 int dp[N]; 6 char s1[N],s2[N]; 7 8 int inline Max(int a,int b) { return a>b?a:b; } 9 10 int main() 11 { 12 int i,j; 13 int pre,next; 14 int len1,len2; 15 while(scanf("%s %s",s1,s2)!=EOF) 16 { 17 len1 = strlen(s1); 18 len2 = strlen(s2); 19 memset(dp,0,sizeof(dp)); 20 for(i=0; i<len1; i++) 21 { 22 next = 0; 23 for(j=0; j<len2; j++) 24 { 25 pre = dp[j]; //pre和next将下一次要用到的dp[i-1][j-1]先存起来,实现空间压缩 26 if(s1[i]==s2[j]) 27 dp[j] = next+1; 28 else 29 dp[j] = Max(dp[j-1],dp[j]); 30 next = pre; 31 } 32 } 33 printf("%d\n",dp[len2-1]); 34 } 35 return 0; 36 }