[POJ 1159] Palindrome

http://poj.org/problem?id=1159

题意:
给你一个字符串,问你至少要插入多少个字符使之成为回文串。

思路:
对于一个回文串来说,其左右两边对应的字符是一样的,所以一个回文串的正串与反串的LCS应该等于回文串的长度。接下来我们考虑普通的字符串,其左右两边对应的字符不一定相同,但我们在统计其正反串的LCS时,可以找到去掉一些字符后,该字符串可以形成的最长的回文串。因此,我们只需要在对应位置插入字符串,就能让其变成回文串,所以答案为原字符串长度 - 正反串LCS的长度。

另外直接开长度为5e3的二维dp数组会MLE。对于LCS而言,我们枚举第一个字符时,其状态只能从上一个字符转移而来,所以可以采用滚动数组的方式来降低空间复杂度。

#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>

using namespace std;

const int N = 5e3 + 7;

char a[N];
int dp[2][N], n;

void solve() {
    int now = 1;
    for (int i = 0; i < n; ++i) {
        for (int j = n - 1; j >= 0; --j) {
            dp[now][j] = max(dp[now^1][j], dp[now][j + 1]);
            if (a[i] == a[j]) dp[now][j] = max(dp[now ^ 1][j + 1] + 1, dp[now][j]);
        }
        now ^= 1;
    }
    printf("%d\n", n - dp[now ^ 1][0]);
}

int main() {
    scanf("%d", &n);
    scanf("%s", a);
    solve();
    return 0;
}
posted @ 2021-03-05 14:13  stff577  阅读(38)  评论(0)    收藏  举报