1. 给定两个序列,X={x1,x2,......xm} 和Y={y1,y2,.....yn},求X和Y的最长公共子序列(LCS)的问题。
对于i=0,1,2....m, X 的第i前缀为Xi={X1,....Xi}, 例如X={A,B,C,D,E,F},则X4={A,B,C,D},假定Z={z1,z2...zk}为上述序列的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
在求X和Y的LCS的过程中,如果xm=yn,我们需要求Xm-1和Yn-1的LCS,并将xm加入到LCS中即可,但是当xm!=yn的时候需要求解Xm-1和Y的LCS和
X和Yn-1的LCS,并选两者较长的一个LCS。
根据上面的分析,可以得到递推公式,c[i][j]表示的是Xi和Yj的LCS的长度
c[i][j]=0, i或者j为0
c[i][j]=c[i-1][j-i]+1, i,j 大于0,并且xi=yj
c[i][j]=max{c[i-1][j],c[i][j-1]}, i,j 大于0,并且xi!=yj
源码:
#include<iostream>
#include<string>
using namespace std;
#define MAXLENGTH 1000
//计算最长公共子序列
int caculateLcs(int ** count, int** label, char x[], char y[], int xLength, int yLength)
{
for (int j = 0; j < xLength + 1; j++)
{
count[j][0] = 0;
}
for (int j = 0; j < yLength + 1; j++)
{
count[0][j] = 0;
}
for (int i = 1; i <= xLength; i++)
{
for (int j = 1; j <= yLength; j++)
{
if (x[i - 1] == y[j - 1])
{
count[i][j] = count[i - 1][j - 1] + 1;
label[i - 1][j - 1] = 4;
}
else if (count[i - 1][j] >= count[i][j - 1])
{
count[i][j] = count[i - 1][j];
label[i - 1][j - 1] = 5;
}
else
{
count[i][j] = count[i][j - 1];
label[i - 1][j - 1] = 1;
}
}
}
return count[xLength][yLength];
}
//打印最长公共子序列
void printLcs(int** label, char x[], int i, int j)
{
if (i == 0 || j == 0)
{
return;
}
if (label[i - 1][j - 1] == 4)
{
printLcs(label, x, i - 1, j - 1);
cout << x[i - 1] << "--";
}
else if (label[i - 1][j - 1] == 5)
{
printLcs(label, x, i - 1, j);
}
else
{
printLcs(label, x, i, j - 1);
}
}
int main()
{
char x[MAXLENGTH] = { 0 };
char y[MAXLENGTH] = { 0 };
cout << "shu ru x: ";
cin >> x;
cout << endl;
cout << "shu ru y: ";
cin >> y;
cout << endl;
int xLength = strlen(x);
int yLength = strlen(y);
int** label = new int*[xLength];
for (int i = 0; i < xLength; i++)
{
label[i] = new int[yLength];
}
int** count = new int*[xLength + 1];
for (int i = 0; i < xLength + 1; i++)
{
count[i] = new int[yLength + 1];
}
int result = caculateLcs(count, label, x, y, xLength, yLength);
cout << "最长公共子序列长度为:" << result << endl;
cout << "最长公共子序列为:";
printLcs(label, x, xLength, yLength);
cout << endl;
delete[]label;
delete[]count;
system("PAUSE");
return 0;
}