思路:区间dp+贪心,先n^2处理出每段区间是否是回文串,然后贪心地找每一段1到i的最少分割。
代码:
#include<bits/stdc++.h> using namespace std; #define ll long long #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) const int N=4e3+5; string s; int n; int dp[N][N]; int ans[N]; int pre[N]; void init(){ for(int len=1;len<=n;len++){ for(int i=0;i+len-1<n;i++){ int j=i+len-1; dp[i][j]=s[i]==s[j]&&(i+1>=j-1||dp[i+1][j-1]); } } } void dfs(int t){ if(pre[t]==-1){ for(int i=0;i<=t;i++)cout<<s[i]; if(t!=n-1)cout<<' '; else cout<<endl; return ; } else{ dfs(pre[t]); for(int i=pre[t]+1;i<=t;i++)cout<<s[i]; if(t!=n-1)cout<<' '; else cout<<endl; return ; } } int main(){ ios::sync_with_stdio(false); cin.tie(0); cin>>s; n=s.size(); init(); for(int i=0;i<n;i++){ ans[i]=(i-1<0?0:ans[i-1])+1; pre[i]=i-1; for(int j=0;j<i;j++){ if(dp[j][i]&&(j-1<0?0:ans[j-1])+1<ans[i]){ ans[i]=(j-1<0?0:ans[j-1])+1; pre[i]=j-1; } } } cout<<ans[n-1]<<endl; dfs(n-1); return 0; }