您的位置:首页 > 其它

【简单dp】poj 1458 最长公共子序列【O(n^2)】【模板】

2015-08-08 09:26 585 查看
最长公共子序列可以用在下面的问题时:给你一个字符串,请问最少还需要添加多少个字符就可以让它编程一个回文串?

解法:ans=strlen(原串)-LCS(原串,反串);

Sample Input

abcfbc         abfcab
programming    contest
abcd           mnp

Sample Output

4
2
0

代码:


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#include <iostream>
#include <string>
#include <algorithm>

using namespace std;

char s[10100], t[10100];
int dp[10100][10100];
//dp[i+1][j+1]:表示序列s的前i个和序列t的前j个的最长公共子序列
//因为字符串从0下标开始存储的 dp[][]数组的0行 0列都被初始化为0
//比如说s[0]=t[0] 就会推出dp[0+1][0+1]=dp[0][0]+1=1
//dp[1][1]=1 也就是s的前1个和t的前1个序列中最长序列为1

int LCS()
{
int i, j;
int len1=strlen(s); int len2=strlen(t);

for(i=0; i<len1; i++) dp[i][0]=0;
for(i=0; i<len2; i++) dp[0][i]=0;

for(i=0; i<len1; i++){
for(j=0; j<len2; j++){
if(s[i]==t[j]) dp[i+1][j+1]=dp[i][j]+1;

else
dp[i+1][j+1]=max(dp[i+1][j], dp[i][j+1]);
}
}
return dp[len1][len2];
}

int main()
{
while(scanf("%s", s)!=EOF){
scanf("%s", t);
int ans=LCS();
printf("%d\n", ans );
}
return 0;
}


现在我修改了字符串开始存储的位置,这样:scanf("%s", s+1); 从下标1开始存储,注意 正确的 len=strlen(s+1);

代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#include <iostream>
#include <string>
#include <algorithm>

using namespace std;

char s[10100], t[10100];
int dp[10100][10100];
//dp[i+1][j+1]:表示序列s的前i个和序列t的前j个的最长公共子序列
//因为字符串从0下标开始存储的 dp[][]数组的0行 0列都被初始化为0
//比如说s[0]=t[0] 就会推出dp[0+1][0+1]=dp[0][0]+1=1
//dp[1][1]=1 也就是s的前1个和t的前1个序列中最长序列为1

int LCS()
{
int i, j;
int len1=strlen(s+1); int len2=strlen(t+1);

for(i=0; i<=len1; i++) dp[i][0]=0;
for(i=0; i<=len2; i++) dp[0][i]=0;

for(i=1; i<=len1; i++){
for(j=1; j<=len2; j++){
if(s[i]==t[j]) dp[i][j]=dp[i-1][j-1]+1;

else
dp[i][j]=max(dp[i-1][j], dp[i][j-1]);
}
}
return dp[len1][len2];
}

int main()
{
while(scanf("%s", s+1)!=EOF){
scanf("%s", t+1);
int ans=LCS();
printf("%d\n", ans );
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: