您的位置:首页 > 产品设计 > UI/UE

动态规划LCS问题( HDU - 1159 Common Subsequence)

2017-02-18 07:48 375 查看
题意:最长公共子集裸

求解LCS问题的解法描述网上有很多很详细的,不过几乎都差不多。大概就是,公共子集Z中,对于zi有三种可能:

1.zi=xk=yj,则dp[k][j]=dp[k-1][j-1]+1;

2.zi=xk&&xk!=yj或者zi=yj&&yj!=xk,这个时候归为一条式子即 dp[k][j]=max(dp[k-1][j],dp[k][j-1]);

当然还存在全不相等的情况,但这种时候最终也会回归到2中。

代码如下:

for(int i=0;i<len1;i++){
for(int j=0;j<len2;j++){
if(a[i]==b[j]){
dp[i+1][j+1]=dp[i][j]+1;
}else{
dp[i+1][j+1]=max(dp[i][j+1],dp[i+1][j]);
}
}
}
这道题我是看着题解做的(因为太菜了。。。)不过我看的那位的初始化我不是很理解,后来看到一张图我瞬间想起来刚开学的时候居然看到过求解LCS问题orz。那么初始化其实就是把最左一列和最上一行全部设为0,然后下标从一开始就好了。

就是这张图(出处见水印)。是不是好理解很多。

相同的把左上角加一,不同则取上和左的max,分析就是上文。

这个还可以用来求回文串,把字符串倒一下就好了。其实我第一次看到这张图就是回文串的题目(然而并没有看懂



完整代码:

/*HDU-1159 LIS问题
*/

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<vector>
#define INF 100000000
#define MAXNUM 1007
#define pi 3.1415926

using namespace std;
char a[MAXNUM];
char b[MAXNUM];
int dp[MAXNUM][MAXNUM];

void lcs(int len1,int len2)
{

/*这样子好理解一点。。*/
int maxlen=max(len1,len2);
for(int i=0;i<=maxlen;i++){
dp[i][0]=0;
dp[0][i]=0;
}
for(int i=0;i<len1;i++){
for(int j=0;j<len2;j++){
if(a[i]==b[j]){
dp[i+1][j+1]=dp[i][j]+1;
}else{
dp[i+1][j+1]=max(dp[i][j+1],dp[i+1][j]);
}
}
}

/*别人的初始化*/

// for(int i=0;i<len1;i++){
// for(int j=0;j<len2;j++){
// if(i==0||j==0){
// if(a[i]==b[j])dp[i][j]=1;
// else{
// if(i==0&&j==0)dp[i][j]=0;
// else{
// i==0?dp[i][j]=dp[i][j-1]:dp[i][j]=dp[i-1][j];
// }
// }
/*对其他的处理*/
// }else{
// if(a[i]==b[j]) dp[i][j]=dp[i-1][j-1]+1;
// else{
// dp[i][j]=max(dp[i][j-1],dp[i-1][j]);
// }
// }
// }
// }
}

int main()
{
while(scanf("%s%s",a,b)!=EOF){
int len1=strlen(a);
int len2=strlen(b);
lcs(len1,len2);
int ans=dp[len1][len2];
printf("%d\n",ans);
memset(dp,0,sizeof(dp));
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
}
return 0;
}(话说我的前几篇博文一直在被审核。。我到底干了什么。。orz
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: