1. 程式人生 > >最長公共子序列Lcs (51Nod - 1006)

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

string OS 模板題 != std ring str spa sin

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)