推理過程
記:
xi x序列的前i個字符(前綴)
yj y序列的前j個字符(前綴)
假設z是LCS(x,y)c++
若xm=yn(最後一個字符相同),則不難用反證法證實:
該字符必須是x與y的任一最長公共子序列z(設長度爲k)
的最後一個字符,即zk=xm=yn 且顯然有zk-1∈LCS(xm-1,yn-1)
即z的前綴zk-1是xm-1與yn-1的最長公共子序列。此時,問題轉歸於求
xm-1與yn-1的LCS(x,y)的長度即等於LCS(xm-1,yn-1)的長度+1;數組
若xm≠yn,則以不難用反證法證實:要麼z∈LCS(xm-1,y),要麼z∈LCS(x,yn-1).
因爲zk≠xm,zk≠yn其中至少有一個必成立,若zk≠xm則有z∈LCS(xm-1,y)
,相似的,若zk≠yn則有z∈LCS(x,yn-1),此時,問題劃歸於求xm-1與y的LCS
及x與yn-1的LCS。LCS(x,y)的長度爲:max(LCS(xm-1,y),LCS(想,yn-1))
的長度spa
由與上述當xm≠yn的狀況時,求LCS(xm-1,y)的長度與LCS(x,yn-1)的長度
這兩個問題是不相互獨立:
二者都須要求LCS(xm-1,yn-1)的長度。另外兩個序列的LCS包含了兩個序列
前綴的LCS,故問題具備最優子結構考慮用動態規劃code
也就是說,解決這個問題,需求:
1:LCS(xm-1,yn-1)+1;
2: LCS(xm-1,y),LCS(x,yn-1)
3:max(LCS(xm-1,y),LCS(x,yn-1))blog
咱們定義c[i,j]表示xi和yi的LCS的長度
若是i=0或j=0,即一個序列長度爲0,那麼LCS爲0;
根據LCS問題的最優子結構性質,可獲得以下公式:遞歸
0 若i=0或j=0;
c[i,j]=c[i-1,j-1]+1 若i,j>0&&xi=yi
max(c[i-1,j],c[i,j-1]) 若i,j>0&&xi≠yiip
1 #include <bits/stdc++.h> 2 #include <stdio.h> 3 #define maxn 1005 4 #include <string> 5 #include <algorithm> 6 7 int dp[maxn][maxn]={0}; 8 using namespace std; 9 10 int comm_subsequence(char *a,char *b,int len1,int len2){ 11 for(int i=1;i<=len1;i++){ 12 for(int j=1;j<=len2;j++){ 13 if(a[i-1]==b[j-1]){ 14 dp[i][j]=dp[i-1][j-1]+1; 15 }else{ 16 dp[i][j]=max(dp[i-1][j],dp[i][j-1]); 17 } 18 } 19 } 20 21 return dp[len1][len2]; 22 } 23 24 int main(){ 25 char a[maxn]; 26 char b[maxn]; 27 while(scanf("%s %s",a,b)!=EOF){ 28 int len1=strlen(a); 29 int len2=strlen(b); 30 memset(dp,0,sizeof(dp)); 31 int tmp=comm_subsequence(a,b,len1,len2); 32 printf("%d\n",tmp); 33 } 34 return 0; 35 }