uva 11404 Palindromic Subsequence (dp+字典序最小路径)


  Palindromic Subsequence 

A Subsequence is a sequence obtained by deleting zero or more characters in a string. A Palindrome is a string which when read from left to right, reads same as when read from right to left. Given a string, find the longest palindromic subsequence. If there are many answers to it, print the one that comes lexicographically earliest.


Constraints

  • Maximum length of string is 1000.
  • Each string has characters `a' to `z' only.

Input 

Input consists of several strings, each in a separate line. Input is terminated by EOF.

Output 

For each line in the input, print the output in a single line.

Sample Input 

aabbaabb
computer
abzla
samhita

Sample Output 

aabbaa
c
aba
aha


题意:

给定一个字符串,要求你删除尽量少的字符,使得原字符串变为最长回文串,并把回文串输出,如果答案有多种,则输出字典序最小的。


思路:

dp[i][j]表示i~j得到的最大回文串,

if(s[i]==s[j]) dp[i][j]=dp[i+1][j-1]+2;

else  dp[i][j]=max(dp[i+1][j],dp[i][j-1]);

这样能得到最大的长度,记录路径后能得到一组解,但是不能得到字典序最小的解。(谈到字典序就要想到求出的是否是最小字典序)

因为在dp[i+1][j]=dp[i][j-1]的时候而且开头字母相同的时候不知道怎样选取,如pkgoxdyddjau。

所以只能用string来记录路径了。

也可以把字符串逆序,然后求两个字符串的LCS,并记录LCS,长度就等于最长回文串的长度,不过求出来的LCS不一定是回文串,如1 5 2 4 3 3 2 4 5 1,只需要知道前半段就行,后半段构造。


代码:(方法一)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#define maxn 1005
#define MAXN 100005
#define mod 100000000
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-6
typedef long long ll;
using namespace std;

int n,m,ans,cnt,tot,k;
char s[maxn];
int dp[maxn][maxn];
string ds[maxn][maxn];

int main()
{
    int i,j,t;
 //   freopen("out.txt","w",stdout);
    while(gets(s+1)!=NULL)
    {
        n=strlen(s+1);
        if(n==0)
        {
            printf("\n");
            continue ;
        }
        memset(dp,0,sizeof(dp));
        for(i=1;i<=n;i++)
        {
            dp[i][i]=1;
            ds[i][i]=s[i];
        }
        for(int len=2;len<=n;len++)
        {
            for(i=1;i<=n;i++)
            {
                j=i+len-1;
                if(j>n) break ;
                if(s[i]==s[j])
                {
                    dp[i][j]=dp[i+1][j-1]+2;
                    ds[i][j]=s[i]+ds[i+1][j-1]+s[j];
                }
                else
                {
                    if(dp[i+1][j]>dp[i][j-1])
                    {
                        dp[i][j]=dp[i+1][j];
                        ds[i][j]=ds[i+1][j];
                    }
                    else if(dp[i+1][j]<dp[i][j-1])
                    {
                        dp[i][j]=dp[i][j-1];
                        ds[i][j]=ds[i][j-1];
                    }
                    else
                    {
                        dp[i][j]=dp[i+1][j];
                        if(ds[i+1][j]<ds[i][j-1]) ds[i][j]=ds[i+1][j];
                        else ds[i][j]=ds[i][j-1];
                    }
                }
            }
        }
 //       printf("%d\n",dp[1][n]);
        cout<<ds[1][n]<<endl;
    }
    return 0;
}
/*
bxxzxcsdgvsgaxxk
xxzxaxx
bxxzxcaxxxbk
b
aabbaabb
computer
abzla
samhita
xcvabxcy
baba
pkgoxdyddjau
*/





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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值