问题 : 给定2个序列X={x1,x2,…,xm}和 Y={y1,y2,…,yn},找出X和Y的最长公共子序列。
动态规划的基本思想:如果能够保存已解决的子问题的答案,而在需要时再找出已求得的答案,就可以避免大量重复计算,从而得到多项式时间算法。
动态规划的基本步骤:
1、找出最优解的性质,并刻画其结构特征。
2、递归地定义最优值。
3、以自底向上的方式计算最优值。
4、根据计算最优值时得到的信息,构造最优解。
此题递归关系:
c[i][j] = 0 ; i = j = 0;
= c[i - 1][j - 1], x[i] = y[j]; i, j > 0, x[i] = y[j];
= max{ c[i][j - 1], c[i - 1][j] }; i, j > 0; x[i] != y[j]
代码:
#include<bits/stdc++.h>
using namespace std;
char x[1020], y[1020], z[1020];
int c[1020][1020], b[1020][1020];
int m, n;
void LCSLength()
{
memset(c, 0, sizeof(c));
memset(b, 0, sizeof(b));
for(int i = 1; i <= m; ++i)
{
for(int j = 1; j <= n; ++j)
{
if(x[i] == y[j])
{
c[i][j] = c[i - 1][j - 1] + 1;
b[i][j] = 1;
}
else if(c[i - 1][j] >= c[i][j - 1])
{
c[i][j] = c[i - 1][j];
b[i][j] = 2;
}
else
{
c[i][j] = c[i][j - 1];
b[i][j] = 3;
}
}
}
}
void LCS(int i, int j)
{
if(i == 0 || j == 0)
return ;
if(b[i][j] == 1)
{
LCS(i - 1, j - 1);
cout << x[i];
}
else if(b[i][i] == 2)
{
LCS(i - 1, j);
}
else
{
LCS(i, j - 1);
}
}
void Input()
{
gets(x);
gets(y);
m = strlen(x);
n = strlen(y);
strcpy(x + 1, x);//为了方便,0号位置不放元素
strcpy(y + 1, y);
}
int main()
{
Input();
LCSLength();
LCS(m, n);
}