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
    评论
这段代码也可以实现在一个区间内寻找回文数并计算它们的和。 其中 `isPalindromic` 函数用于判断一个数是否为回文数,`getInputs` 函数用于获取区间的上边界和下边界,并检查用户的输入是否合法。在主程序中,我们首先调用 `getInputs` 函数获取区间的上边界和下边界,然后通过循环遍历这个区间,找到其中所有回文数,并将它们存储在一个列表中。最后,我们计算这些回文数的总和,并输出结果。 这段代码的工作流程与之前的示例代码基本相同,唯一的区别是在输入区间时,代码将上边界和下边界分别存储在 `upper` 和 `lower` 变量中,并检查它们的大小关系。如果用户输入的上边界比下边界小,则交换它们的值,以确保下边界始终小于或等于上边界。 下面是这段代码的完整实现: ```python def isPalindromic(n): s = str(n) return s == s[::-1] def getInputs(): count = 0 while count < 3: try: upper = int(input("请输入区间的上边界:")) lower = int(input("请输入区间的下边界:")) if upper > lower: upper, lower = lower, upper return upper, lower except: print("输入有误,请重新输入!") count += 1 print("输入错误次数过多,程序退出!") exit() palindromic_list = [] upper, lower = getInputs() for i in range(lower, upper + 1): if isPalindromic(i): palindromic_list.append(i) total = sum(palindromic_list) print("区间[{},{}]中的回文数为:{}".format(lower, upper, palindromic_list)) print("它们的和为:{}".format(total)) ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值