给一个长度为 5000的串
找出 最少插入多少个字符 得到一个回文串
思路1:
把该串和其逆序 求一遍 LCS. 答案就是len-lcs
思路2:
dp
if (tm[i]==tm[j]) dp[i][j]=dp[(i+1)][j-1]; else dp[i][j]=min(dp[(i+1)][j],dp[i][j-1])+1;
由于内存太大,用dfs不好用上滚动数组。。。
dfs版本
#include <cstdio> #include <cmath> #include <cstring> #include <string> #include <algorithm> #include <iostream> #include <queue> #include <map> #include <set> #include <vector> using namespace std; int min(int a,int b) {return a<b?a:b;} int min(int a,int b,int c) { return min(c,min(a,b));} char tm[5005]; int dp[5005][5005]; const int inf=1147483647; int dfs(int i,int j) { if (i>j) return 0; if (i==j) return dp[i][j]=0; if (dp[i][j]) return dp[i][j]; if (tm[i]!=tm[j]) return dp[i][j]=min(dfs(i+1,j),dfs(i,j-1))+1; else return dp[i][j]= dfs(i+1,j-1); } int main() { int n; cin>>n; scanf("%s",tm); int len=n; dfs(0,n-1); printf("%d\n",dp[0][n-1]); return 0; }
滚动数组版本
#include <cstdio> #include <cmath> #include <cstring> #include <string> #include <algorithm> #include <iostream> #include <queue> #include <map> #include <set> #include <vector> using namespace std; int min(int a,int b) {return a<b?a:b;} int min(int a,int b,int c) { return min(c,min(a,b)); } char tm[5005]; short dp[2][5005]; int main() { int n; cin>>n; scanf("%s",tm); int len=n; int i,j; for (i=n-1;i>=0 ;i--) { for (j=i+1;j<n;j++) { if (tm[i]==tm[j]) dp[i&1][j]=dp[(i+1)&1][j-1]; else dp[i&1][j]=min(dp[(i+1)&1][j],dp[i&1][j-1])+1; //因为推dp[i][j]需要(后面)i+1的情况和(前面)j-1的情况,所以决定了2个循环的方向不同 } } printf("%d\n",dp[0][n-1]); return 0; }