您的位置:首页 > 其它

LCS问题——动态规划

2015-03-27 20:34 239 查看
简述: LCS问题,即最长公共子序列问题,给定两个序列X={x1, x2, …, xm}和Y={y1, y2, …, yn},求X、Y最长的公共子序列。与LIS类似,LCS也是可以不连续的。

解题思路:本人觉得在这个问题上算法导论讲的很好,所以在此我主要是整理。

1、首先我们来考虑暴力搜索求解的方法,我们要暴力枚举X的所有子序列,然后再看看是不是也是Y的子序列,这样的方法,显然时间复杂度是指数级的,所以并不可取,但是,我们是否能从中看到些什么呢?

2、我们来看看LCS是不是具有最优子结构:

之前说的暴力求解,在程序中怎么表达呢?考虑一个序列Z={z1, z2, …, zk},他是X、Y的一个LCS序列:

如果xm==yn,就意味着xm肯定在Z序列里,而且是zk;

如果xm!=yn,那么说明xm和yn至多有一个在Z里面,所以这里X、Y的LCS就有两种可能性:X(1…m-1)与Y(1…n)的LCS和X(1…m)与Y(1…n-1)的LCS;

于是有最优子结构!

3、从上面就可以看出来了,没错,就是深搜!但是,太慢了。所以,记忆化一下就行了!

于是……用dp[i][j]表示X(1…i)和Y(1…j)的LCS,那么有状态转移方程

if(x[i]==y[j])
dp[i][j]=dp[i-1][j-1]+1;
else
dp[i][j]=max(dp[i-1][j],dp[i][j-1]);


完整代码:(可以用POJ_1458测试一下)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

int m,n,x[1005],y[1005],ans,dp[1005][1005];
char st1[1005],st2[1005];

int main()
{
while(~scanf("%s %s",st1,st2))
{
m=strlen(st1),n=strlen(st2);
for(int i=0;i<m;i++)
x[i+1]=st1[i];
for(int i=0;i<n;i++)
y[i+1]=st2[i];

ans=0;
memset(dp,0,sizeof(dp));
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
if(x[i]==y[j])
dp[i][j]=dp[i-1][j-1]+1;
else
dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
}
}
printf("%d\n",dp[m]
);
}

return 0;
}


总结:

1、之前一直不知道LCS是啥,今天算是了解了一下;

2、果然深搜是王道啊!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: