-----Edit by ZhuSenlin HDU
求最长公共子序列。给定两个序列和 ,希望找出X和Y的最大公共子序列。
1) 确定LCS最优子结构。设为X和Y的任意一个LCS,则
如果xm=yn,那么zk=xm=yn且Zk-1是Xm-1和Yn-1的一个LCS;
如果xm!=yn,那么zk!=xm蕴含Z是Xm-1和Y的一个LCS;
如果xm!=yn,那么zk!=yn蕴含Z是X和Yn-1的一个LCS
2) 寻找递归解
设C[i,j]为序列Xi和Yj的一个LCS的长度。则
3) 计算长度
创建一个表Table存放每一个(i,j)对应的LCS的长度。则C[Length(X)][Length(Y)]为X与Y的LCS长度。
创建另外一个表Path记录路径,如果则Path[i][j]=’x’(斜),如果则Path[i][j]=’u’(up),如果则Path[i][j]=’l’(left)。
代码如下:
template <class T>
void CreateTable(T**& pTable, int nH, int nW)
{
DeleteTable(pTable,nH);
pTable = new T* [nH];
for(int i = 0; i < nH; i++) {
pTable[i] = new T[nW];
memset(pTable[i],0,nW*sizeof(T));
}
}
template <class T>
void DeleteTable(T**& pTable, int nH)
{
if(!pTable)
return;
for(int i = 0; i < nH; i++)
if(pTable[i])
delete pTable[i];
delete pTable;
}
int LengthLCS(const char* pStrA, const char* pStrB, int**& pTable, char**& pPath)
{
int nLengthA = strlen(pStrA);
int nLengthB = strlen(pStrB);
for(int i = 1; i<= nLengthA; i++){
for(int j = 1; j <= nLengthB; j++) {
if(pStrA[i-1] == pStrB[j-1]) {
pTable[i][j] = pTable[i-1][j-1]+1;
pPath[i][j] = 'x';
}
else if(pTable[i-1][j] < pTable[i][j-1]){
pTable[i][j] = pTable[i][j-1];
pPath[i][j] = 'l';
}
else {
pTable[i][j] = pTable[i-1][j];
pPath[i][j] = 'u';
}
}
}
return pTable[nLengthA][nLengthB];
}
void PrintLCS(char** pPath, const char* pStrA,int nLengthA, int nLengthB)
{
if(nLengthA == 0 || nLengthB == 0)
return;
if(pPath[nLengthA][nLengthB] == 'x') {
PrintLCS(pPath, pStrA, nLengthA-1, nLengthB-1);
cout << pStrA[nLengthA-1] << " ";
}
else if(pPath[nLengthA][nLengthB] == 'l')
PrintLCS(pPath,pStrA,nLengthA,nLengthB-1);
else
PrintLCS(pPath,pStrA,nLengthA-1,nLengthB);
}
测试代码如下:
int main()
{
const char* pStrA = "abcbdab";
const char* pStrB = "bdcaba";
int** pTable = NULL;
char** pPath = NULL;
int nLengthA = strlen(pStrA);
int nLengthB = strlen(pStrB);
CreateTable(pTable,nLengthA+1,nLengthB+1);
CreateTable(pPath,nLengthA+1,nLengthB+1);
cout << LengthLCS(pStrA,pStrB,pTable,pPath) << endl;
PrintLCS(pPath,pStrA,strlen(pStrA),strlen(pStrB));
cout << endl;
DeleteTable(pTable,strlen(pStrA)+1);
DeleteTable(pPath,strlen(pStrA)+1);
return 0;
}
参考书籍:算法导论