动态规划-最长公共子序列
有关概念:
最长公共子序列(LCS,Longest Common Subsequence),两个或者两个以上序列的所有共同子序列最长的一个(好像和没解释没什么区别)
思路:
对于两个序列a,b
f[i][j]表示a序列中1..i的部分和b序列中1...j的部分的LCS
那么易得,对于f[i][j]:
(1)如果ai!=bj,则从f[i-1][j]和f[i][j-1]中挑选较大的作为前驱,继承其值;
(2)否则,则使f[i-1][j-1]作为其前驱,继承其值并++;
最后输出f[lena][lenb]即可……
当然,可以在更新f[i][j]的时候附带更新数组记录其前驱的位置,以便最后输出
(我TM都讲些什么东西)
给出数组代码,如果是字符串的话,适当改动即可
1 #include<cstdio> 2 #define MAXN 3 int lena,lenb,a[MAXN],b[MAXN],ans1,ans2[MAXN]; 4 struct node 5 { 6 int x,nextx,nexty; 7 }f[MAXN][MAXN]; 8 int main() 9 { 10 scanf("%d",&lena); 11 for(int i=1;i<=lena;++i)scanf("%d",&a[i]); 12 scanf("%d",&lenb); 13 for(int i=1;i<=lenb;++i)scanf("%d",&b[i]); 14 for(int i=1;i<=lena;++i) 15 for(int j=1;j<=lenb;++j) 16 { 17 if(a[i]==b[j])f[i][j]=(node){f[i-1][j-1].x+1,i-1,j-1}; 18 else 19 { 20 if(f[i-1][j].x>f[i][j-1].x)f[i][j]=(node){f[i-1][j].x,i-1,j}; 21 else f[i][j]=(node){f[i][j-1].x,i,j-1}; 22 } 23 } 24 printf("%d\n",f[lena][lenb].x); 25 int x=lena,y=lenb; 26 while(x&&y) 27 { 28 node temp=f[x][y]; 29 x=temp.nextx;y=temp.nexty; 30 if(f[x][y].x==temp.x-1)ans2[++ans1]=a[x+1]; 31 } 32 for(int i=ans1;i>=1;--i)printf("%d ",ans2[i]); 33 return 0; 34 }