UVA 11404 Palindromic Subsequence

题目大意:求最长回文子串,并输出其中字典序最小的。

思路:转化为LCS。将原来字符串反转,得到str2,然后和原字符串求LCS,求LCS的过程中还需要记录每一个状态所对应的的LCS,因为之后要比较。然后再分两种情况(1)回文串为偶数,那么当str1位置为i时,str2的位置应为len-i。(2)为奇数,那么考虑中间字母为str1[ i ]时,str1的位置为i-1,str2的位置为len-i,这里还需要注意,中间位置要从str[1]开始枚举,因为左、右边可以为空。

很好的题,因为先开始自己想到LCS,但是不会找字典序最小的,原来只要把每个状态d[ i ][ j ] 的s都记录下来就可以了,代码用C++写比较方便,但是对C++不是很熟,代码很多都是照着别人的代码来的。。 = =

代码如下:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;

const int MAXN = 1111 ;

char str[MAXN];
char str2[MAXN];

struct Node
{
    int len;
    string s;
    bool operator < (const Node & tmp) const
    {
        if(len == tmp.len)
        {
            return s>tmp.s;
        }
        else return len<tmp.len;
    }
} d[MAXN][MAXN];

int len;

void LCS()
{
    for(int i = 0;i<=len;i++)
    {
        d[0][i].len = 0;
        d[0][i].s.clear();
        d[i][0].len = 0;
        d[i][0].s.clear();
    }
    for(int i = 1;i<=len;i++)
    {
        for(int j = 1;j<=len;j++)
        {
            if(str[i]==str2[j])
            {
                d[i][j].len = d[i-1][j-1].len+1;
                d[i][j].s = d[i-1][j-1].s + str[i];
            }
            else
            {
                d[i][j] = max(d[i-1][j],d[i][j-1]);
            }
        }
    }
}

string roll(string s)
{
    string tmp="";
    for(int i = s.length()-1;i>=0;i--)
        tmp += s[i] ;
    return tmp;
}

int main()
{
    while(cin>>(str+1))
    {
        len = strlen(str+1);
        for(int i = 1;i<=len;i++)
        {
            str2[i] = str[len-i+1];
        }
        LCS();
        Node ans;
        ans.len = 0;
        ans.s.clear();
        for(int i = 1;i<len;i++)
            ans = max(ans,d[i][len-i]);
        ans.len *= 2;
        ans.s += roll(ans.s);
        Node tmp;
        for(int i = 1;i<=len;i++)
        {
            tmp.len = 2*d[i-1][len-i].len+1;
            tmp.s = d[i-1][len-i].s + str[i] + roll(d[i-1][len-i].s);
            ans = max(ans,tmp);
        }
        cout<<ans.s<<endl;
    }
    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值