题意:问一个字符串最少插入多少个字符可以将其变成回文串。
思路:
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; }