推理过程
记:
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 }