最长公共子序列(longest common sequence)和最长公共子串(longest common substring)不是一回事儿。什么是子序列呢?即一个给定的序列的子序列,就是将给定序列中零个或多个元素去掉之后得到的结果。
我们可以知道递推公式为:
0; i=0 or j=0;
c[i][j]= c[i-1][j-1]+1; i,j>0;xi=yi;
max{c[i][j-1],c[i-1][j]}; i,j>0;xi!=yi;
递归法解决:
#include<stdio.h>
#include<string.h>
int maxL(char *x,char *y,int i,int j){
int t1,t2;
if(i==-1||j==-1)
return 0;
if(x[i]==y[j])
return maxL(x,y,i-1,j-1)+1;
else{
t1=maxL(x,y,i-1,j);
t2=maxL(x,y,i,j-1);
return t1>t2?t1:t2;
}
}
int main(){
char *x="ABCBDAB",*y="BDCABA";
printf("最大子序列长度:%d\n",maxL(x,y,lenx,leny));
return 0;
}
动态规划法解决:
int main(){
char *x="ABCBDAB",*y="BDCABA";
int **c;
int lenx,leny;
lenx=strlen(x);
leny=strlen(y);
c=new int *[lenx+1];
for(int i=0;i<lenx+1;i++)
c[i]=new int[leny+1];
for(int i=0;i<lenx+1;i++)
c[i][0]=0;
for(int i=0;i<leny+1;i++)
c[0][i]=0;
for(int i=1;i<lenx+1;i++)
for(int j=1;j<leny+1;j++){
if(x[i-1]==y[j-1])
c[i][j]=c[i-1][j-1]+1;
else
c[i][j]=c[i-1][j]>c[i][j-1]?c[i-1][j]:c[i][j-1];
}
printf("最大子序列长度:%d",c[lenx][leny]);
return 0;
}
备忘录法解决:
int **c;
int maxL(char *x,char *y,int i,int j){
int t1,t2,result;
if(c[i][j]>=0)
return c[i][j];
if(x[i-1]==y[j-1])
result=maxL(x,y,i-1,j-1)+1;
else{
t1=maxL(x,y,i-1,j);
t2=maxL(x,y,i,j-1);
result=t1>t2?t1:t2;
}
c[i][j]=result;
return result;
}
int main(){
char *x="ABCBDAB",*y="BDCABA";
int lenx,leny;
lenx=strlen(x);
leny=strlen(y);
c=new int *[lenx+1];
for(int i=0;i<lenx+1;i++)
c[i]=new int[leny+1];
for(int i=0;i<lenx+1;i++)
for(int j=0;j<leny+1;j++)
c[i][j]=-1;
for(int i=0;i<lenx+1;i++)
c[i][0]=0;
for(int i=0;i<leny+1;i++)
c[0][i]=0;
printf("最大子序列长度:%d\n",maxL(x,y,lenx,leny));
printf("%d",c[lenx][leny]);
return 0;
}