题意: 在串中划分出最少个数的回文串。输出最少回文串的个数,并将回文串输出。
think: 首先肯定是区间问题。
还是没自己解决这个问题看了题解。
dp[i]表示以i结束最少的回文串的个数。
枚举区间预处理出该区间是否为字符串,
然后如果区间j~i是回文串的话, 那么转移方程则为 dp[i] = min(dp[j-1]+1, dp[i])[然后还要记录路径,这里就和bfs记 录 路径差不多]。
#include <bits/stdc++.h> #define ll long long #define ms(x) memset(x, 0, sizeof(x)) #define inf 0x3f3f3f3f #define mf(x) memset(x, inf, sizeof(x)) using namespace std; const int N = 4123; int dp[N], pre[N]; bool isPa[N][N]; char s[4123]; vector<int>q; int main() { while(scanf("%s", s+1) != EOF) { int len = strlen(s+1); ms(isPa); ms(pre); q.clear(); for(int i=1;i<=len;i++){ isPa[i][i] = 1; int l = i, r = i; while(l>=1 && r<=len && s[l] == s[r]){ isPa[l][r] = 1; l--, r++; } l = i, r = i+1; while(l>=1 && r<=len && s[l] == s[r]){ isPa[l][r] = 1; l--, r++; } } mf(dp); dp[0] = 0; pre[1] = 0; for(int i=1;i<=len;i++){ for(int j=i;j>=1;j--){ if(isPa[j][i]){ if(dp[i]>(dp[j-1] + 1)){ dp[i] = dp[j-1] + 1; pre[i] = j-1; } } } } printf("%d\n", dp[len]); int tp = pre[len]; q.push_back(len); while(tp!=0){ q.push_back(tp); tp = pre[tp]; } q.push_back(0); for(int i=q.size()-1; i>=1; i--){ if(i!=q.size()-1) printf(" "); for(int l = q[i]+1; l<=q[i-1]; l++){ printf("%c", s[l]); } } printf("\n"); } return 0; }