添加最少的字符让字符串变为回文字符串(1)

添加最少的字符让字符串变为回文字符串(1)

题目描述

给定一个字符串str,如果可以在str的任意位置添加字符,请返回在添加字符最少的情况下,让str整体都是回文字符串的一种结果。

输入描述:

输入包含一行字符串,代表 s t r ( 1 ≤ l e n g t h s t r ≤ 5000 ) str(1 \leq length_{str} \leq 5000) str(1lengthstr5000)

输出描述:

输出一行,代表返回的字符串。

示例1
输入
ABA
输出
ABA
示例2
输入
AB
输出
ABA
备注:

时间复杂度 O ( n 2 ) O(n^2) O(n2),空间复杂度 O ( n 2 ) O(n^2) O(n2)


题解:

动态规划,设 F[i, j] 表示子串 s[i…j] 最少添加几个字符可以使得 s[i…j] 整体是回文串,F[i, j] 有下面三种情况:

  • 只有一个字符,那么明显的:F[i, j] = 0;
  • 只有两个字符,若两个字符相等,则 F[i, j] = 0;否则的话,只需要添加一个字符,则 F[i, j] = 1;
  • 多于两个字符,若 s[i] == s[j] ,则 F[i, j] = F[i+1, j-1] ;否则的话,F[i, j] = min{F[i+1, j], F[i, j-1]} + 1。

在输出时,只需要根据动态规划表还原即可。

代码:
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 5001;

char s[N];
int f[N][N];
char ret[N << 1];

int main(void) {
    
    
    scanf("%s", s);
    int len = strlen(s);
    for (int i = 0; i < len - 1; ++i)
        f[i][i + 1] = (s[i] != s[i + 1]);
    for (int i = len - 2; i >= 0; --i) {
    
    
        for (int j = i + 2; j < len; ++j) {
    
    
            if (s[i] == s[j]) f[i][j] = f[i + 1][j - 1];
            else f[i][j] = min(f[i + 1][j], f[i][j - 1]) + 1;
        }
    }
    int i = 0, j = len - 1;
    int tot_len = len + f[0][len - 1];
    int l = 0, r = tot_len - 1;
    while (i <= j) {
    
    
        if (s[i] == s[j]) {
    
    
            ret[l++] = s[i++];
            ret[r--] = s[j--];
        } else if (f[i + 1][j] < f[i][j - 1]) {
    
    
            ret[l++] = ret[r--] = s[i++];
        } else {
    
    
            ret[l++] = ret[r--] = s[j--];
        }
    }
    puts(ret);
    return 0;
}

猜你喜欢

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