参考《算法导论》译本(原书第二版)P208页
子序列的概念:一个给定序列的子序列就是该给定序列中去掉零个或者多个元素。
公共子序列:给定两个序列X和Y,如果Z既是X的一个子序列又是Y的一个子序列,则序列Z是X和Y的一个公共子序列。
最长公共子序列:X和Y的所有公共子序列中长度最长的公共子序列。
实现如下:
enum ValueFrom
{
TOPLEFT=0,
TOP,
LEFT
};
string getResult(enum ValueFrom** valueFromArray,string x,int rows,int cols) //此部分的时间复杂度为O(xLen+yLen),在递归的每个阶段,rows和cols至少有一个在减小
{
string strRet;
if(rows==0||cols==0)
{
strRet.clear();
return strRet;
}
if(valueFromArray[rows][cols]==TOPLEFT)
{
strRet.push_back(x.at(rows-1));
strRet.append(getResult(valueFromArray,x,rows-1,cols-1));
}
else if(valueFromArray[rows][cols]==TOP)
strRet.append(getResult(valueFromArray,x,rows-1,cols));
else
strRet.append(getResult(valueFromArray,x,rows,cols-1));
return strRet;
}
string getLongestCommonSubString(string x,string y)
{
string strResult;
strResult.clear();
int xLen=x.length();
int yLen=y.length();
if(xLen==0||yLen==0)
return strResult;
int** flagArray=new int*[xLen+1];
for(int i=0;i<xLen+1;i++)
flagArray[i]=new int[yLen+1];
enum ValueFrom** valueFromArray=new enum ValueFrom*[xLen+1];
for(int i=0;i<xLen+1;i++)
valueFromArray[i]=new enum ValueFrom[yLen+1];
//第一行第一列全部赋值为0
for(int i=1;i<xLen+1;i++)
flagArray[i][0]=0;
for(int j=0;j<yLen+1;j++)
flagArray[0][j]=0;
for(int i=1;i<xLen+1;i++) //此部分代码的时间复杂度为O(xLen*yLen)
{
char cx=x.at(i-1);
for(int j=1;j<yLen+1;j++)
{
char cy=y.at(j-1);
if(cx==cy)
{
flagArray[i][j]=flagArray[i-1][j-1]+1;
valueFromArray[i][j]=TOPLEFT;
}
else
{
if(flagArray[i-1][j]>=flagArray[i][j-1])
{
flagArray[i][j]=flagArray[i-1][j];
valueFromArray[i][j]=TOP;
}
else
{
flagArray[i][j]=flagArray[i][j-1];
valueFromArray[i][j]=LEFT;
}
}
}
}
strResult=getResult(valueFromArray,x,xLen,yLen);
reverse(strResult.begin(),strResult.end());
for(int i=0;i<xLen+1;i++)
{
delete[] flagArray[i];
flagArray[i]=NULL;
}
delete[] flagArray;
for(int i=0;i<xLen+1;i++)
{
delete[] valueFromArray[i];
valueFromArray[i]=NULL;
}
delete[] valueFromArray;
return strResult;
}
实现步骤基本上与书中一致,没有什么好解释的,书中介绍的非常详细。
所用测试代码为书中的两个DNA螺旋和解释算法的过程用到的例子:
int _tmain(int argc, _TCHAR* argv[])
{
string x="ACCGGTCGAGTGCGCGGAAGCCGGCCGAA";
string y="GTCGTTCGGAATGCCGTTGCTCTGTAAA";
string strRet=getLongestCommonSubString(x,y);
cout<<strRet<<endl;
x="ABCBDAB";
y="BDCABA";
strRet=getLongestCommonSubString(x,y);
cout<<strRet<<endl;
return 0;
}
整个算法的时间复杂度为O(xLen*yLen)。