您的位置:首页 > 其它

算法导论第15章 最长公共子序列问题(LCS)

2013-12-19 16:40 225 查看

最长公共子序列问题:

给定两个两个序列X= <x1, x2, ....., xm>和Y = <y1, y2, ...., yn>,希望找出X和Y的最大长度的公共子序列,可以使用动态规划来解决

定理15.1(LCS的最优子结构)
设X= <x1, x2, ....., xm>和Y = <y1, y2, ...., yn>为两个序列,并设Z = {z1, z2, ....,zk}为X和Y的任意一个LCS
(1)如果xm = yn, 那么zk = xm = yn, 而且Zk-1是Xm-1与Yn-1的一个LCS
(2)如果xm != yn,那么Zk != xm蕴含Z是Xm-1和Y的一个LCS
(3)如果xm != yn, 那么Zk != yn,蕴含Z是X和Yn-1的一个LCS

定义c[i][j]为序列Xi与Yi的一个LCS长度,则有下面递归表达式
0 若i = 0 或 j = 0;

c[i][j] = c[i-1][j-1]+1 若i, j > 0 且xi = yi;

max(c[i][j-1], c[i-1][j]) 若i,j > 0 且 xi != yi;

根据上面的递归式可以写出自底向上的动态规划代码

#include <iostream>
using namespace std;

const int m = 8;
const int n = 7;

//返回值结构
struct twoArrayPair
{
char b[m]
;
int c[m]
;
};

/*************************************************************/
/*
c[m]
:保存了X和Y的LCS长度
b[m]
: 帮助构造最优解

0                          若i = 0 或 j = 0;
c[i][j] =  c[i-1][j-1]+1              若i, j > 0 且xi = yi;
max(c[i][j-1], c[i-1][j])  若i,j > 0 且 xi != yi;
*/
/*************************************************************/
twoArrayPair *LCSLength(char *x,a char *y)
{
twoArrayPair *twoArray = new twoArrayPair;

//c, b数组初始化
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
(twoArray->b)[i][j] = ' ';
(twoArray->c)[i][j] = 0;
}
}

for (int i = 1; i < m; i++)
{
for (int j = 1; j < n; j++)
{
if (x[i] == y[j])
{
(twoArray->c)[i][j] = (twoArray->c)[i-1][j-1]+1;
(twoArray->b)[i][j] = '\\';
}
else if ((twoArray->c)[i-1][j] >= (twoArray->c)[i][j-1])
{
(twoArray->c)[i][j] = (twoArray->c)[i-1][j];
(twoArray->b)[i][j] = '|';
}
else
{
(twoArray->c)[i][j] = (twoArray->c)[i][j-1];
(twoArray->b)[i][j] = '-';
}
}
}
return twoArray;
}

//打印LCS
void printLCS(char (*b)
, char *x, int i, int j)
{
if (i == 0 | j == 0)
return;
if (b[i][j] == '\\')
{
printLCS(b, x, i-1, j-1);
cout << x[i];
}
else if (b[i][j] == '|')
printLCS(b, x, i-1, j);
else
printLCS(b, x, i, j-1);
}

int main()
{
char x[] = "0ABCBDAB";
char y[] = "0BDCABA";

twoArrayPair *tt = LCSLength(x, y);
cout << "x与y的最长公共子序列是:" << endl;
printLCS(tt->b, x, m-1, n-1);
cout << endl;

system("pause");
return 0;
}


运行结果为:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: