poj 1159 Palindrome (反串LCS 与 DP两种方法)

题目链接http://poj.org/problem?id=1159

LCS之前只写了一次,反串了以后都没有反应过来可以用LCS。。。

给出反串LCS代码:

//反串LCS 
#include<iostream> 
#include<cstring>
#include<cmath>
using namespace std;

int n;
char s[5005];
char rs[5005];
int dp[2][5005];///滚动数组 

int lcs(char* str1,char* str2){ 
    memset(dp,0,sizeof(dp));
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            if(str1[i-1]==str2[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]);
        }
    return dp[n%2][n];
}
int main(){
    
    while(cin>>n>>s){
    int i;
    for(i=0;i<n;i++)
        rs[i]=s[n-i-1];
    rs[i]='\0';
    cout<<n-lcs(s,rs)<<endl;
    }
    return 0;
}
View Code

但是据说有动态规划的做法,就沿着动态规划的思路想了想,发现其实很简单

给出基本DP做法

/*
动态规划思想 
我们先从上至下的分析 

以题目数据做例子
假如字符串Ab3bd已经找到最优的最少插入方法,设为dp(Ab3bd) 
那么,我们想得出b3bd的最优解 
因为A与b3bd的最后一个字符d不相同,说明排除A以后,就可以省掉一个插入,则dp(b3bd)=dp(Ab3bd)-1 
同理,dp(Ab3b)=dp(Ab3bd)-1 

如果把字符串改成
Ab3bdA
那么dp(b3bdA)=dp(Ab3bd)=dp(Ab3bdA)+1

我们就发现了关系
if(i==j)
    dp(i....j)=dp(i+1...j)-1 //此时dp(i+1....j)==dp(i....j-1) 
else
    dp(i....j)=min( dp(i+1....j)+1,dp(i....j-1)+1 )//此时dp(i+1...j)!=dp(i...j-1) 

实现:
设dp[i][j]为从i到j的最优解 
可以看出,在求dp[i][j]时,dp[i+1][j]和dp[i][j-1]就已经要求出来了
所以有i递减,j递增的顺序(显然i从n递减,j从i递增) 
答案就是 dp[1][n] 

算法时间O(n^2) 
*/ 
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;

int n;
char s[5005];
int dp[2][5005];

int main (){
    while(cin>>n>>s){
        memset(dp,0,sizeof(dp));//dp[i][i]=0
        for(int i=n-1;i>=1;i--)
            for(int j=i+1;j<=n;j++)
            {    
                if(s[i-1]==s[j-1])
                    dp[i&1][j]=dp[(i+1)&1][j]-1;
                else
                    dp[i&1][j]=min(dp[(i+1)&1][j],dp[i&1][j-1])+1;
            }
        cout<<dp[1][n]<<endl;
    }
    return 0;
}

 

其实后来发现s[i-1]==s[j-1]时,dp[i][j]=dp[i+1][j-1]。。。貌似好一点

posted @ 2014-02-25 23:00  neverchanje  阅读(149)  评论(0编辑  收藏  举报