有两个字符串,求两者最长公共子串的长度,如“ZHAOQINGEN”和“QZAO”的最长公共子串的AO,返回长度为2。
分析:显然可以用动态规划来做,设c[i][j]表示Xi={x1,x2,x3。。。xi}与Yj={y1,y2,。。。yj}的最长公共字串序列的长度;如果xi与yj形同,那么c[i][j]=c[i-1][j-1]+1;否则取c[i][j-1]与c[i-1][j]的较大值。其次要注意初始化i=0或j=0,c[i][][j]=0;
代码如下:
// [7/7/2013 qingezha] 动态规划 最长公共子序列 c[i][j]表示Xi={x1,x2,x3。。。xi}与Yj={y1,y2,。。。yj}的最长公共字串序列的长度
int lcs_length(char x[],char y[],int b[LA+1][LB+1],int c[LA+1][LB+1])
{
for (int i=1;i<=LA;++i) c[i][0]=0; //需要判断指针是否为空;数组需要初始化,否则值不一定
for (int i=1;i<=LB;++i) c[0][i]=0;
for (int i=1;i<=LA;++i)
{
for (int j=1;j<=LB;++j)
{
if (x[i]==y[j]) //序列从1开始计数
{
c[i][j]=c[i-1][j-1]+1;//把c[i][j] 写成了c[i][i]了,重大失误,造成4个小时的浪费
b[i][j]=1;
}
else if(c[i-1][j]>=c[i][j-1])
{
c[i][j]=c[i-1][j];
b[i][j]=2;
}
else
{
c[i][j]=c[i][j-1];
b[i][j]=3;
}
}
}
测试代码//
for (int i=1;i<=LA;++i) //可以将数据输出来看看,哪里有不符合逻辑的错误
{
for (int j=1;j<=LB;++j)
{
cout<<b[i][j];
}
cout<<endl;
}
cout<<endl;
for (int i=1;i<=LA;++i)
{
for (int j=1;j<=LB;++j)
{
cout<<c[i][j];
}
cout<<endl;
}
cout<<endl;
char x[7+2]=" abcdefx";
char y[7+2]=" aecxdfx";
int b[8][8]={{0}};
int c[8][8]={{0}};
int a[8]={0};
cout<<lcs_length(x,y,b,c)<<endl;
lcs(7,7,x,b);
//
return c[LA][LB];
}
以及输出的最长的公共子序列的代码如下
void lcs(int i,int j,char x[],int b[LA+1][LB+1])
{
if(0==i||0==j) return;
if (b[i][j]==1)
{
lcs(i-1,j-1,x,b);
cout<<x[i]<<" ";
}
else if(2==b[i][j])
lcs(i-1,j,x,b);
else lcs(i,j-1,x,b);
}