例如,若 X = {A, B, C, B, D, A, B },
Y = {B, D, C, A, B, A },
設序列X=<x1, x2, …, xm>和Y=<y1, y2, …, yn>的一個最長公共子序列Z=<z1, z2, …, zk>,則:
若xm=yn,則zk=xm=yn且Zk-1是Xm-1和Yn-1的最長公共子序列;
若xm≠yn且zk≠xm,則Z是Xm-1和Y的最長公共子序列;
若xm≠yn且zk≠yn,則Z是X和Yn-1的最長公共子序列。
由此遞歸結構容易看到最長公共子序列問題具有子問題重疊性質。例如,在計算X和Y的最長公共子序列時,可能要計算出X和Yn-1及Xm-1和Y的最長公共子序列。而這兩個子問題都包含一個公共子問題,即計算Xm-1和Yn-1的最長公共子序列。
LEFT_UP = 0,
UP,
void PrintLCS(const char* pStr, int length1, int length2, int** b)
{
if(pStr == NULL || b == NULL || length1 <=0 || length2 <= 0)
return;
int i=length1, j=length2;
if(b[i][j] == LEFT_UP)
{
PrintLCS(b, pStr, i-1, j-1);
printf("%c ", pStr[i-1]);
}
else if(b[i][j] == UP)
PrintLCS(b, pStr, i-1, j);
else
PrintLCS(b, pStr, i, j-1);
void LCS_Length(const char* pStr1, const char* pStr2)
{
if (pStr1 == NULL || pStr2 == NULL)
throw new std::exception("Invalid Parameter!");
int str1Length = strlen(pStr1);
int str2Length = strlen(pStr2);
if(str1Length == 0 || str2Length == 0)
return;
int** c = (int**)new int[str1Length+1];
int** b = (int**)new int[str1Length+1];
for (int i=0; i<str1Length+1; ++i)
{
c[i] = new int[str2Length+1];
b[i] = new int[str2Length+1];
memset(c[i], 0, str2Length+1);
memset(b[i], 0, str2Length+1);
}
for (int i=1; i<=str1Length; ++i)
for (int j=1; j<=str2Length; ++j)
{
if (pStr1[i-1] == pStr2[j-1])
{
c[i][j] = c[i-1][j-1] + 1;
b[i][j] = LEFT_UP;
}
else if(c[i-1][j] >= c[i][j-1])
{
c[i][j] = c[i-1][j];
b[i][j] = UP;
}
else
{
c[i][j] = c[i][j-1];
b[i][j] = LEFT;
}
}
std::cout<<"str1:"<<pStr1<<std::endl<<"str2:"<<pStr2<<std::endl;
PrintLCS(pStr1, str1Length, str2Length, b);
for(int i=0; i<str1Length+1; ++i)
{
delete[] c[i];
delete[] b[i];
}
delete[] c;
delete[] b;
}
{
char* pStr1 = "ABCBDAB";
char* pStr2 = "BDCABAB";
LCS_Length(pStr1, pStr2);
return 0;
str2:BDCABAB