题意:问一个字符串最少插入多少个字符可以将其变成回文串。
思路:
f(i, k) 为 从i开始长度为k 的字串变成回文串最少需要插入字符数。
看见discuss明白了这个口以看作 原串长-正逆串lcs。。
不过开二维数组会mle, 不过貌似空间减半就可以了,所以直接有人用压缩矩阵或者改用short。。
我用f1,f2分别保存上个和上上个状态,空间消耗5000*2。。
//#include<bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <queue>
#include <stack>
#include <cassert>
#include <algorithm>
#include <cmath>
#include <climits>
#include <set>
#include <map>
using namespace std;
#define SPEED_UP iostream::sync_with_stdio(false);
#define FIXED_FLOAT cout.setf(ios::fixed, ios::floatfield);
#define rep(i, s, t) for(int (i)=(s);(i)<=(t);++(i))
#define urep(i, s, t) for(int (i)=(s);(i)>=(t);--(i))
typedef long long LL;
const int Maxn = 5000;
const int inf = INT_MAX/2;
char a[Maxn+5];
int f1[Maxn+5], f2[Maxn+5], len;
int f(int l, int r) {
if (l >= r) return 0;
if (r-l+1 == len-2) return f2[l];
return f1[l];
}
int main() {
#ifndef ONLINE_JUDGE
freopen("input.in", "r", stdin);
#endif
SPEED_UP
int n;
cin >> n >> a;
rep(k, 2, n)
rep(i, 0, n-k) {
int j = i+k-1, tmp = inf;
len = k;
tmp = min(f(i+1, j), f(i, j-1))+1;
if (a[i] == a[j])
tmp = min(tmp, f(i+1, j-1));
else
tmp = min(tmp, f(i+1, j-1)+2);
f2[i] = f1[i];
f1[i] = tmp;
//cout << "f(" << i << ", " << j << ") " << f[i][j] << endl;
}
cout << f(0, n-1) << endl;
return 0;
}