算法设计与分析——最长公共子序列问题
题目描述:
简述最长公共子序列问题及求解方法。
设两个长度为n和m的字符串A和B
A=a1,a2,...an
B=b1,b2,...bn
令L[i,j]表示a1,a2,...ai和b1,b2,...bj的最长公共子序列的长度,则A和B最长公共子序列的关系递推式为:
例如,Z={b,c,d,b}是序列X={a,b,c,b,d,a,b}的子序列,相应的递增下标序列为{2,3,5,7}。给定2个序列X和Y,当另一个序列Z即是X的子序列又是Y的子序列时,称Z是序列X和Y的公共子序列。
例题:
B | z | x | y | y | z | x | z | ||
---|---|---|---|---|---|---|---|---|---|
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ||
A | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
x | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 |
z | 2 | 0 | 1 | 1 | 1 | 1 | 2 | 2 | 2 |
y | 3 | 0 | 1 | 1 | 2 | 2 | 2 | 2 | 2 |
z | 4 | 0 | 1 | 1 | 2 | 2 | 3 | 3 | 3 |
z | 5 | 0 | 1 | 1 | 2 | 2 | 3 | 3 | 4 |
y | 6 | 0 | 1 | 1 | 2 | 3 | 3 | 3 | 4 |
x | 7 | 0 | 1 | 2 | 2 | 3 | 3 | 4 | 4 |
最长公共子序列:
xyzz
zyzz
代码实现(根据递推式记忆)
void LCSLength(char *x, char *y, int m, int n, int L[][MAXLEN])
{
//字符串x长度为m,字符串y长度为n,L中存放最长公共子序列长度
int i,j;
for(i=0;i<=m;i++)
L[i][0]=0;
for(j=1;j<=n;j++)
L[0][j]=0;
for(i=1;i<=m;i++)
{
for(j=1;j<=n;j++)
{
if(x[i]==y[i])
{
L[i][j]=L[i-1][j-1]+1; //记忆
}
else if(x[i]!=y[i]) //记忆
{
L[i][j]=L[i-1][j];
}
else
{
L[i][j]=L[i][j-1];
}
}
}
return L[m][n]; //记忆
}