动态规划分为四个步骤:
1.判断问题是否具有最优子结构
这里以LCS为例,X={x1,x2,…,xi};Y={y1,y2,…,yj}。最长公共子序列Z={z1,z2,…,zk};
①如果xi=yj,那么zk=xi=yj,且Zk-1是序列Xi-1和Yj-1的LCS;
②如果xi≠yj,那么zk≠xi;且Zk是序列Xi-1和Yj的LCS;
③如果xi≠yj,那么zk≠yj;且Zk是序列Xi和Yj-1的LCS;
2.一个递归解
设c[i,j]是Xi和Yj的LCS的长度,i=0或j=0时,c[i,j]=0;
c[i,j]=0 (i=0或j=0)
c[i,j]=c[i-1,j-1] + 1 (i,j>0;xi=yj)
c[i,j]=max{c[i-1,j],c[i,j-1]} (i,j>0;xi≠yj)
3.计算LCS的长度
c[i,j]为递归解,那么有多少个不同的递归解呢?O(m*n)。即要有重叠子问题,而不是每次都要解决新的问题。至于重叠子问题,需从底向上求。每次只需索引之前较小规模的子问题即可。
从底向上,求解c[i,j]。
#include <list>
#include <vector>
#include <iostream>
using namespace std;
int lcg_length(const string &X, const string &Y)
{
if(X.empty() || Y.empty())
return 0;
int m = X.size();
int n = Y.size();
vector<vector<int>> c;
for(int i = 0; i < m+1; ++ i)
{
vector<int> tmp(n+1, 0);
c.push_back(tmp);
}
for(int i = 1; i <= m; ++ i)
{
for(int j = 1; j <= n; ++ j)
{
if(X.at(i-1) == Y.at(j-1))
c[i][j] = c[i-1][j-1] + 1;
else {
c[i][j] = max(c[i-1][j], c[i][j-1]);
}
}
}
return c[m][n];
}
int main()
{
int len = lcg_length("ABCBDAB", "BDCABA");
system("pause");
return 0;
}