LCS问题即 longest common subsequence 最长公共子序列问题,也是经典的DP问题。
做这道题目的时候依旧是和做其他DP题目一样,按照步骤,先找到最优子结构,然后确定递归方程,然后就是填表和计算了。
given a sequence X = 〈x1, x2,
..., xm〉, we define the ith prefix of X,
for i = 0, 1, ..., m, as Xi = 〈x1, x2,
..., xi〉. For example, if X =〈A, B, C, B, D, A, B〉,
then X4 = 〈A, B, C, B〉 and X0 is
the empty sequence.
上面是定义一个序列的Xi前缀。
下面给出LCS的最优子结构
由此我们也可以得出下面的递归式
其中数组c[i,j]存的就是序列Xi与Yj的LCS长度。根据这个递归式就可以写代码了
#include<iostream>
using namespace std;
void LCS_Length(char *X,int xlen,char *Y,int ylen,int ch[][7])
{
int i,j;
for(i = 1; i < xlen; i++)
ch[i][0] = 0;
for(j = 0; j < ylen; j++)
ch[0][j] = 0;
for(i = 1; i < xlen; i++)
{
for(j = 1; j < ylen; j++)
{
if(X[i] == Y[j])
ch[i][j] = ch[i - 1][j - 1] + 1;
else if(ch[i - 1][j] >= ch[i][j - 1])
ch[i][j] = ch[i - 1][j];
else
ch[i][j] = ch[i][j - 1];
}
}
}
void Print_LCS(char *X,int ch[][7],int i,int j)
{
if(i == 0 || j == 0)
return;
if(ch[i][j] == (ch[i - 1][j - 1] + 1))
{
Print_LCS(X,ch,i-1,j-1);
cout<<X[i]<<" ";
}
else if(ch[i][j] == ch[i - 1][j])
Print_LCS(X,ch,i-1,j);
else
Print_LCS(X,ch,i,j-1);
}
int main()
{
char X[] = {'#','B','D','C','B','D','A','B'};
char Y[] = {'#','B','D','C','A','B','A'};
int ch[8][7];
LCS_Length(X,8,Y,7,ch);
Print_LCS(X,ch,7,6);
return 0;
}