http://poj.org/problem?id=1159
题目大意:给定一个字符串,问最少插入多少字符,使该字符串变成回文字符串。
设原字符串序列为X,逆序列为Y,则最少需要补充的字母数=X的长度-X和Y的最长公共子串的长度。
状态转移方程:f[i][j]=max{ f[i-1][j] , f[i][j-1] , f[i-1][j-1]+1(if s1[i]==s2[j])}
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <set> #include <map> #include <cmath> #include <queue> using namespace std; template <class T> void checkmin(T &t,T x) {if(x < t) t = x;} template <class T> void checkmax(T &t,T x) {if(x > t) t = x;} template <class T> void _checkmin(T &t,T x) {if(t==-1) t = x; if(x < t) t = x;} template <class T> void _checkmax(T &t,T x) {if(t==-1) t = x; if(x > t) t = x;} typedef pair <int,int> PII; typedef pair <double,double> PDD; typedef long long ll; #define foreach(it,v) for(__typeof((v).begin()) it = (v).begin(); it != (v).end ; it ++) const int N = 5050; int f[2][N]; int LCS(string s1 , string s2 ,int n) { memset(f , 0 , sizeof(f)); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { f[i%2][j] = max(f[(i-1)%2][j],f[i%2][j-1]); if(s1[i-1] == s2[j-1]) checkmax(f[i%2][j] , f[(i-1)%2][j-1]+1); } return f[n%2][n]; } int main() { string s1 , s2; int n; while(cin >> n) { cin >> s1; s2 = s1; reverse(s1.begin() , s1.end()); cout << n - LCS(s1,s2,n) << endl; } return 0; }