首页 > 代码库 > 动态规划-最长公共子序列

动态规划-最长公共子序列

有关概念:

  最长公共子序列(LCS,Longest Common Subsequence),两个或者两个以上的所有共同子序列最长的一个(好像和没解释没什么区别)

思路:

  对于两个序列a,b

  f[i][j]表示a序列中1..i的部分和b序列中1...j的部分的LCS

  那么易得,对于f[i][j]:

  (1)如果a[i]!=b[j],则从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 }

 

动态规划-最长公共子序列