最長公共子序列Lcs (51Nod - 1006)
阿新 • • 發佈:2018-06-04
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)