最长公共子序列(longest common sequence)
LCS通常利用动态规划算法求解,最简单的求解方式如《算法导论》所述:
1.设输入为X1X2…Xm,Y1Y2…Yn,构造二维数组B、C;
其中B[i][j]存储C[i][j]的最优解指向,C[i][j]存储X[1…i]和Y[1…j]的LCS长度;
2.B、C数组同时更新:
2.1.令B[0][k]、C[0][k](k=0…n)和B[k][0]、C[k][0](k=0…m)为0;
2.2.按下标从小到大的顺序依次计算每行的B[i][j]和C[i][j],规则如下:
①.若X[i]=Y[j],则C[i][j]=C[i-1][j-1]+1,B[i][j]=0;
②.若X[i]!=Y[j],则C[i][j]=Max(C[i][j-1],C[i-1][j]),B[i][j]=1或2;
3.更新完B、C后,从C[m][n]开始递归输出,根据B[i][j]的指向打印LCS;
推理公式:
代码:
int **Lcs_length(string X,string Y,int **B)
{
int x_len = X.length();
int y_len = Y.length();
int **C = new int *[x_len+1];
for (int i = 0; i <= x_len; i++)
{
C[i] = new int[y_len + 1]; //定义一个存放最优解的值的表;
}
for (int i = 1; i <= x_len; i++)
{
C[i][0] = 0;
B[i][0] = -2; //-2表示没有方向
}
for (int j = 0; j <= y_len; j++)
{
C[0][j] = 0;
B[0][j] = -2;
}
for (int i = 1; i <= x_len; i++)
{
for (int j = 1; j <= y_len; j++)
{
if (X[i-1]==Y[j-1])
{
C[i][j] = C[i - 1][j - 1] + 1;
B[i][j] = 0; //0表示斜向左上
}
else
{
if (C[i-1][j]>=C[i][j-1])
{
C[i][j] = C[i - 1][j];
B[i][j] = -1; //-1表示竖直向上;
}
else
{
C[i][j] = C[i][j - 1];
B[i][j] = 1; //1表示横向左
}
}
}
}
return C;
}