UVa:11404 Palindromic Subsequence(动态规划)

问题可以转化成LCS输出最小字典序。

用了一种很笨的办法,直接保存dp过程中的每个公共字符串,这样在两个字符不等时且dp【i-1】【j】==dp【i】【j-1】时来比较两个公共字符串的字典序来确定i,j位置的字符串。这样输出也不用倒推回去了,但是空间复杂度比较高。另外有一个问题时此题要求输出回文,这样得到的结果可以不是回文,所以取前半部分然后逆置出后半部分即是答案。

用了1.2S

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <algorithm>
#define ll long long
#define INF 2139062143
#define inf -2139062144
#define MOD 20071027
#define MAXN 1005
using namespace std;
int dp[MAXN][MAXN];
string path[MAXN][MAXN];
string str1,str2;
int main()
{
    ios::sync_with_stdio(false);
    while(cin>>str1)
    {
        str2.clear();
        int l=str1.size();
        for(int i=l-1; i>=0; --i)
            str2+=str1[i];
        str1='0'+str1;
        str2='0'+str2;
        memset(dp,0,sizeof(dp));
        for(int i=1; i<=l; ++i)
            for(int j=1; j<=l; ++j)
                if(str1[i]==str2[j])
                {
                    dp[i][j]=dp[i-1][j-1]+1;
                    path[i][j]=path[i-1][j-1]+str1[i];
                }
                else
                {
                    if(dp[i-1][j]==dp[i][j-1])
                    {
                        dp[i][j]=dp[i-1][j];
                        path[i][j]=min(path[i-1][j],path[i][j-1]);
                    }
                    else
                    {
                        if(dp[i-1][j]>dp[i][j-1])
                        {
                            dp[i][j]=dp[i-1][j];
                            path[i][j]=path[i-1][j];
                        }
                        else
                        {
                            dp[i][j]=dp[i][j-1];
                            path[i][j]=path[i][j-1];
                        }
                    }
                }
        string ans;
        for(int i=0; i<=(dp[l][l]-1)/2; ++i)
            ans+=path[l][l][i];
        int st;
        if(dp[l][l]%2==0) st=ans.size()-1;
        else st=ans.size()-2;
        for(int i=st; i>=0; --i)
            ans+=ans[i];
        cout<<ans<<endl;
    }
    return 0;
}


 用滚动数组优化之后时间变成了0.8S

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <algorithm>
#define ll long long
#define INF 2139062143
#define inf -2139062144
#define MOD 20071027
#define MAXN 1005
using namespace std;
int dp[3][MAXN];
string path[3][MAXN];
string str1,str2;
int main()
{
    ios::sync_with_stdio(false);
    while(cin>>str1)
    {
        str2.clear();
        int l=str1.size();
        for(int i=l-1; i>=0; --i)
            str2+=str1[i];
        str1='0'+str1;
        str2='0'+str2;
        memset(dp,0,sizeof(dp));
        for(int i=0; i<=l; ++i)
        {
            path[0][i].clear();
            path[1][i].clear();
        }
        for(int i=1; i<=l; ++i)
            for(int j=1; j<=l; ++j)
                if(str1[i]==str2[j])
                {
                    dp[i&1][j]=dp[(i+1)&1][j-1]+1;
                    path[i&1][j]=path[(i+1)&1][j-1]+str1[i];
                }
                else
                {
                    if(dp[(i+1)&1][j]==dp[i&1][j-1])
                    {
                        dp[i&1][j]=dp[(i+1)&1][j];
                        path[i&1][j]=min(path[(i+1)&1][j],path[i&1][j-1]);
                    }
                    else
                    {
                        if(dp[(i+1)&1][j]>dp[i&1][j-1])
                        {
                            dp[i&1][j]=dp[(i+1)&1][j];
                            path[i&1][j]=path[(i+1)&1][j];
                        }
                        else
                        {
                            dp[i&1][j]=dp[i&1][j-1];
                            path[i&1][j]=path[i&1][j-1];
                        }
                    }
                }
        string ans;
        for(int i=0; i<=(dp[l&1][l]-1)/2; ++i)
            ans+=path[l&1][l][i];
        int st;
        if(dp[l&1][l]%2==0) st=ans.size()-1;
        else st=ans.size()-2;
        for(int i=st; i>=0; --i)
            ans+=ans[i];
        cout<<ans<<endl;
    }
    return 0;
}


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值