添加最少的字符让字符串变成回文串(2)

添加最少的字符让字符串变成回文串(2)

题目描述

给定一个字符串str,再给定str的最长回文子序列字符串strlps, 请返回在添加字符最少的情况下,让str整体都是回文字符串的一种结果。进阶问题比原问题多了一个参数,请做到时间复杂度比原问题的实现低。

输入描述:

输出包含两行,第一行包含一个字符串代表 s t r ( 1 ≤ l e n g t h s t r ≤ 5000 ) str(1 \leq length_{str} \leq 5000) str(1lengthstr5000),第二行包含一个字符串,代表strips。

输出描述:

输出一行,代表返回的值。

示例1
输入
A1B21C
121
输出
AC1B2B1CA
说明
str=“A1B21C",strlps="121",返回“AC1B2B1CA”或者“CA1B2B1AC”,总之,只要是添加的字符数最少,只返回其中一种结果即可。

题解:

既然此题给了最长回文子序列,那么我们就要考虑用此子序列搞事情。最长回文子序列肯定出现在最终的回文串中,并且子序列左右部分没有相等的字符(不然会构成更长的回文子序列),并且最终的回文子串长度为:2*len(str)-len(strlps)。我们可以采用 “剥洋葱” 的方式去构造回文串:

  • 在 str 左边找到等于 strlps 第一个字符的位置,设为 sl,在 str 右边找到等于 strlps 最后一个字符(也是第一个字符)的位置,设为 sr;
  • 将 str[0…sl-1] + str[len-1…sr+1]复制到最终子串左半部分,str[sr+1…len-1] + str[sl-1…0]复制到最终子串右半部分,然后将 strlps 首字符复制到最终子串左右部分。
  • 跳过 strlps 首尾字符,继续处理下一个字符,直到 strlps 处理完毕。
代码:
#include <cstdio>
#include <cstring>

using namespace std;

const int N = 5001;

char s[N];
char t[N];
char ret[N << 1];

int main(void) {
    
    
    scanf("%s", s);
    scanf("%s", t);
    int ls = strlen(s);
    int lt = strlen(t);
    int tot_len = (ls << 1) - lt;
    int ss = 0, se = ls - 1;
    int ts = 0, te = lt - 1;
    int rs = 0, re = tot_len - 1;
    while (ts <= te) {
    
    
        while (s[ss] != t[ts]) {
    
    
            ret[rs++] = s[ss];
            ret[re--] = s[ss++];
        }
        while (s[se] != t[ts]) {
    
    
            ret[rs++] = s[se];
            ret[re--] = s[se--];
        }
        ret[rs++] = s[ss++];
        ret[re--] = s[se--];
        ++ts, --te;
    }
    puts(ret);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/MIC10086/article/details/108895813
今日推荐