Timus 1635
令res[i][j]表示从i到j是否是回文串。
res[i][j]= (str[i]==str[j] && res[i+1][j-1]) ;
接下来是如何找最少个数回文串,令inum[i]表示从1到i至少有多少个回文串,再次用DP;
inum[i]=min(inum[j]+1),(其中res[j][i]==1,1<=j<i);
最后根据inum[i]的值寻找一种可行的方案。
O(n^2)的时间复杂度,O(n^2)的空间复杂度,网上还有更好的代码,竟然没有看懂
#include<iostream> #include<cstdio> #include<cstring> #include<stack> using namespace std; #define MAX 1234567890 char str[4010]; int res[4010][4010],start[4010],end[4010],inum[4010],step; int work(int n) { int i,j; for(i=1;i<=n;i++) res[i][i]=res[i][i-1]=1; for(j=1;j<=n;j++) for(i=j-1;i>0;i--) if(str[i]==str[j] && res[i+1][j-1]) res[i][j]=1; return 0; } int GetMin(int n) { int i,j; for(i=1;i<=n;i++) { inum[i]=i; for(j=0;j<i;j++) if(res[j+1][i]) inum[i]= inum[i] < inum[j]+1 ? inum[i] : inum[j]+1; } return inum[n]; } int f(int s,int t) { int i; for(i=s;i<=t;i++) printf("%c",str[i]); return 0; } int GetRes(int n) { int i,j; stack <int> S1; stack <int> S2; i=n; while(i>0) { S2.push(i); for(j=i-1;j>0;j--) { if(res[j+1][i] && inum[j]+1==inum[i]) { S1.push(j+1); break; } } i=j; } S1.push(1); f(S1.top(),S2.top()); S1.pop(); S2.pop(); while(!S1.empty()) { printf(" "); f(S1.top(),S2.top()); S1.pop(); S2.pop(); } printf("\n"); return 0; } int main() { int l; while(scanf("%s",str+1)!=EOF) { l=strlen(str+1); step=l; memset(res,0,sizeof(res)); work(l); printf("%d\n",GetMin(l)); GetRes(l); } return 0; }