题意: 在串中划分出最少个数的回文串。输出最少回文串的个数,并将回文串输出。
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;
}