最长公共子序列Lcs (51Nod - 1006)

Posted chuixulvcao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最长公共子序列Lcs (51Nod - 1006)相关的知识,希望对你有一定的参考价值。

 

20180604   11:28
 
给出两个字符串A B,求A与B的最长公共子序列(子序列不要求是连续的)。
 
比如两个串为:
 
abcicba
abdkscab
 
ab是两个串的子序列,abc也是,abca也是,其中abca是这两个字符串最长的子序列。

Input第1行:字符串A 
第2行:字符串B 
(A,B的长度 <= 1000)Output输出最长的子序列,如果有多个,随意输出1个。Sample Input

abcicba
abdkscab

Sample Output

abca

思路:

⒈模板题,不过输出的不是最长序列有多长而是最长序列是什么。

⒉详解见代码。

          j-1             j   

i-1  (i-1,j-1)    (i-1,j)

 i      (i,j-1)       (i,j)

求最长公共子序列的思路:

?判断末尾是否相等[if(a[i-1]==b[j-1])]=>c[i][j]=c[i-1][j-1]+1;

?不相等=>c[i][j]=max(c[i][j-1],c[i-1][j]);(及选取最大的);

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<iostream>
 4 #include<cstring>
 5 #include<string>
 6 #include<cmath>
 7 #include<algorithm>
 8 using namespace std;
 9 int len1,len2;
10 char a[1001],b[1001];
11 int c[1001][1001];
12 int main()  
13 {
14     cin>>a>>b;
15     len1=strlen(a);
16     len2=strlen(b);
17     memset(c,0,sizeof(c));
18     int i,j;
19     for(i=1;i<=len1;i++)
20         for(j=1;j<=len2;j++)
21         {
22             if(a[i-1]==b[j-1]) c[i][j]=c[i-1][j-1]+1;
23             else c[i][j]=max(c[i-1][j],c[i][j-1]);
24         }
25     int x=len1;
26     int y=len2;
27     int k=c[x][y];//最长序列出现在右下角.(如果把算出来的c[i][j]画成表格的话)
28     char lcs[1001] = {\0};
29     while(i&&j)
30     {
31         if(a[i-1]==b[j-1]&&c[i][j]==c[i-1][j-1]+1)//此时i,j已经到了len1和len2。所以这里是倒着回去看的。
32         {//c[i][j]==c[i-1][j-1]+1证明是从左上角下来的也就是说,左上角位置的a[i-1]和b[j-1]末尾相同。
33             lcs[--k] = a[i-1];//先将k--再用是因为存数据的时候从0开始.
34             i--;
35             j--;
36         }
37         else if(a[i-1]!=b[j-1]&&c[i-1][j]>c[i][j-1])  i--;//看上方图就能明白。
38         else j--;
39     }
40     printf("%s\n",lcs);
41     return 0;  
42 }  

 

以上是关于最长公共子序列Lcs (51Nod - 1006)的主要内容,如果未能解决你的问题,请参考以下文章

最长公共子序列Lcs (51Nod - 1006)

51Nod - 1006 最长公共子序列Lcs模板

51nod 1006 最长公共子序列Lcs(dp+string,无标记数组实现)

模板51nod 1006 最长公共子序列Lcs

51Nod-1006LCS+输出路径模板题

最长公共子序列lcs