最长公共子序列的定义是,一个数列z分别是已知数列的子序列(子序列不一定是连续序列,是在该序列中删去若干元素后得到的序列),且是所有符合此条件序列中最长的,则z成为最长公共子序列lcs(Longest Common Subsequences)。有些地方则说公共子串就是要求连续的子序列,有些地方则不是,这里要注意区分。下面是完整实现代码。
#include <iostream>
using namespace std;
void LCS_Length(char *x,char *y,int **b,int m,int n)
{
//c[i][j]表示x[i-1],y[j-1]之前公共子序列的长度,i表示x数组前进,j表示y数组前进
//不用c[i][j]表示x[i],y[j]之前公共子序列的长度是因为需要使用c[0][0]来表示没有公共子序列,
//即c[0][0]恒等于0,因此c数组最大下标为c[m+1][n+1]
int **c;
c=new int*[m+1];
for( int i=0;i<m+1;i++)
c[i]=new int[n+1];
for(int i=0;i<m+1;i++)
c[i][0]=0;
for(int i=0;i<n+1;i++)
c[0][i]=0;
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
if(x[i-1]==y[j-1])//找到一个公共“字符”
{
c[i][j]=c[i-1][j-1]+1;//公共子序列的长度在原来的基础上加1
b[i][j]=0;//做一个辅助标志,表示要达到目前的长度,x,y数组均需“前进”一步
//即x[i-1],y[j-1]都要作出贡献
}
//当前字符不相同,且x数组后退一步(即c[i-1][j])比y数组后退一步(即c[i][j-1])
//所得到的公共子序列的长度要长,隐含的意思是当前最长公共子序列可以不需要x[i-1]
else if(c[i-1][j]>=c[i][j-1])
{
c[i][j]=c[i-1][j];//当前最长公共子序列可以不需要x[i-1]
b[i][j]=-1;
}
//和上面分析类似
else
{
c[i][j]=c[i][j-1];//当前最长公共子序列可以不需要y[j-1]
b[i][j]=1;
}
}
}
for(int i=0;i<m+1;i++)
{
delete c[i];
c[i]=NULL;
}
delete []c;
c=NULL;
}
//打印结果
void Print_LCS(int **b,char *x,int i,int j)
{
if(i==0||j==0)
return ;
if(b[i][j]==0)
{
Print_LCS(b,x,i-1,j-1);
cout<<x[i-1];
}
else if(b[i][j]==-1)
Print_LCS(b,x,i-1,j);
else
Print_LCS(b,x,i,j-1);
}
int _tmain(int argc, _TCHAR* argv[])
{
char x[]="ADAB";
char y[]="ADCA";
int m=strlen(x);
int n=strlen(y);
int **b;
b=new int*[m+1];
for( int i=0;i<m+1;i++)
b[i]=new int[n+1];
LCS_Length(x,y,b,m,n);
Print_LCS(b,x,m,n);
for(int i=0;i<m+1;i++)
{
delete b[i];
b[i]=NULL;
}
delete []b;
b=NULL;
return 0;
}