Xij = Zj
如果一个序列S即是A的子序列又是B的子序列,则称S是A、B的公共子序列。
求A、B所有公共子序列中最长的序列的长度。
格式:printf("%d\n");
contest
思路分析:动态规划问题具有最优子结构性质和子问题重叠性质。
a) 最长公共子序列的结构
若用穷举搜索法,耗时太长,算法需要指数时间。
易证最长公共子序列问题也有最优子结构性质
设序列X=<x1, x2, …, xm>和Y=<y1, y2, …, yn>的一个最长公共子序列Z=<z1, z2, …, zk>,则:
i. 若xm=yn,则zk=xm=yn且Zk-1是Xm-1和Yn-1的最长公共子序列;
ii. 若xm≠yn且zk≠xm,则Z是Xm-1和Y的最长公共子序列;
iii. 若xm≠yn且zk≠yn,则Z是X和Yn-1的最长公共子序列。
其中Xm-1=<x1, x2, …, xm-1>,Yn-1=<y1, y2, …, yn-1>,Zk-1=<z1, z2, …, zk-1>。
最长公共子序列问题具有最优子结构性质。
b) 子问题的递归结构
由最长公共子序列问题的最优子结构性质可知,要找出X=<x1,x2, …, xm>和Y=<y1, y2,…, yn>的最长公共子序列,可按以下方式递归地进行:当xm=yn时,找出Xm-1和Yn-1的最长公共子序列,然后在其尾部加上xm(=yn)即可得X和Y的一个最长公共子序列。当xm≠yn时,必须解两个子问题,即找出Xm-1和Y的一个最长公共子序列及X和Yn-1的一个最长公共子序列。这两个公共子序列中较长者即为X和Y的一个最长公共子序列。
由此递归结构容易看到最长公共子序列问题具有子问题重叠性质。例如,在计算X和Y的最长公共子序列时,可能要计算出X和Yn-1及Xm-1和Y的最长公共子序列。而这两个子问题都包含一个公共子问题,即计算Xm-1和Yn-1的最长公共子序列。
我们来建立子问题的最优值的递归关系。用c[i,j]记录序列Xi和Yj的最长公共子序列的长度。其中Xi=<x1,x2, …, xi>,Yj=<y1,y2, …, yj>。当i=0或j=0时,空序列是Xi和Yj的最长公共子序列,故c[i,j]=0。建立递归关系如下:
代码如下,已经经过测试。
#include <iostream>
#include <string.h>
using namespace std;
char x[200], y[200];
int num[201][201];
int get_length(char x[], char y[]);
int main()
{
cin >> x >> y;
//cout << x << y;
cout << get_length(x, y) << endl;
}
int get_length(char x[], char y[])
{
int n, m;
n = strlen(x);
m = strlen(y);
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= m; j++)
{
if(x[i - 1] == y[j - 1])
num[i][j] = num [i - 1][j - 1] + 1;
else
{
if(num[i - 1][j] > num[i][j - 1])
num[i][j] = num[i-1][j];
else num[i][j] = num[i][j-1];
}
}
}
return num[n][m];
}