-----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; }
参考书籍:算法导论