您的位置:首页 > 其它

最长公共子序列(LCS)

2011-05-27 21:24 218 查看
对于最长公共子序列(LCS),是典型的动态规划问题,对于这个问题,可以用如下思路来解答。
如:X{x1, x2, x3, ... },Y{y1, y2, y3, ...};
1.当x1 = y1时,则此时已找到一个相同的值,故接下来只需求{x2, x3, x4, ...}和{y2, y3, y4, ...}的LCS。
2.当x1 != y1时,则此时X和Y的LCS是下面两个LCS的最大值:
{x2, x3, x4, ...}和{y1, y2, y3, y4, ...}的LCS,
或者{x1, x2, x3, x4, ...}和{y2, y3, y4, ...}的LCS。
由上面可以看出这是一个递归问题。

_
| 0 i==0或j==0
|
c[i][j] = |- c[i-1][j-1] + 1 如果i,j>0和xi==yj
|
|_ max{c[i][j-1], c[i-1][j]} 如果i,j>0和xi != yj
其实通过代码中的嵌套for循环,即可知道每次通过比较来累积计算长度的。

#include <iostream>
#include <cstring>
using namespace std;

char* LCS(const char* x, const char* y);

int main()
{
char* x = "cbfgade";
char* y = "bcagfde";

char* s = LCS(x, y);
cout<<"最长公共子序列为:"<<s<<endl;
cout<<"长度为:"<<strlen(s)<<endl;
return 0;
}

char* LCS(const char* x, const char* y)
{
int m = strlen(x);
int n = strlen(y);

int** c = new int*[m + 1];
for (int i = 0; i < m + 1; i++) {
c[i] = new int[n + 1];
//每一行第一个元素初始化为0
c[i][0] = 0;
}

//第一行初始化为0
for (int i = 0; i < n + 1; i++)
c[0][i] = 0;

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

//c[m]
值为最短子序列的长度
//用result来保存逆序LCS,通过c[m]
的值与c[m - 1][ n - 1],c[m][n - 1],c[m - 1]
来判断
int len = c[m]
;
char* result = new char[len + 1];
int count = len;
while (m > 0 && n > 0) {
if (c[m]
== c[m - 1][ n - 1] + 1 && x[m - 1] == y[n - 1]) {
result[--count] = x[m - 1];
m--;
n--;
} else if (c[m]
== c[m][n - 1]) {
n--;
} else {
m--;
}
}
result[len] = '\0';

//释放内存
for (int i = 0; i < m + 1; i++)
delete[] c[i];
delete []c;

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