首页 > 代码库 > POJ 1159 Palindrome && HDU 1159 Common Subsequence

POJ 1159 Palindrome && HDU 1159 Common Subsequence

1、先说说杭电的1159吧!

这道题是基础动规,比较简单!

就是要你求最长的公共子序列(不要优化)

动态转移方程: dp[i+1][j+1]=(a[i]=b[i])?dp[i][j]+1:max(dp[i+1][j],dp[i][j+1])

AC代码: 

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define N 520
char a[N],b[N];
int dp[N][N];
int main()
{
    int i,j,len_a,len_b;
    while(scanf("%s %s",a,b)!=EOF)
    {
        len_a=strlen(a);
        len_b=strlen(b);
        for(i=1;i<=len_a;i++)
            for(j=1;j<=len_b;j++)
            {
                if(a[i-1]==b[j-1])
                    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[len_a][len_b]);
    }
    return 0;
}

2、再说POJ1159:

题意是给你一个字符串,要你算出它成为回文串需要多少字母

Ab3bd
db3bA
本质为求字符串及其逆序串的最长公共子序列(LCS)
如果你还想用刚刚那方法,不好意思,空间复杂度为5K*5K
果断送给了POJ1个Memory Limit Exceeded!
之前学了个滚动数组来优化空间,现在可以考虑了滚动数组优化空间复杂度
注意到dp[i][j]只和dp[i-1][j-1],dp[i-1][j],dp[i][j-1]三个值相关,我们可以只保留两行的数据即可,这样使用两个数组滚动计算即可
所以,AC代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define N 5005
int dp[2][N];
char str[N],cstr[N];
int main()
{
    int i,j,t;
    scanf("%d",&t);
    scanf("%s",str);
    for(i=0;i<t;i++){
        cstr[i]=str[t-i-1];
        dp[0][i]=dp[1][i]=0;
    }
    dp[0][t]=dp[1][t]=0;
    for(i=1;i<=t;i++)
        for(j=1;j<=t;j++)
        {
            if(str[i-1]==cstr[j-1])
                dp[i%2][j]=dp[(i-1)%2][j-1]+1;
            else
                dp[i%2][j]=max(dp[(i-1)%2][j],dp[i%2][j-1]);
        }
    printf("%d\n",t-dp[t%2][t]);
    return 0;
}