题目大意
给你一个字符串,划分成尽量少的回文串,要求字串在原串中是连续的。
解法
用一个dp数组存储最优解,dp[i]表示字符0~i至少需要划分多少回文串。用pal[i][j]数组表示i~j是否是一个回文串,对于pal数组需要预处理。dp的状态转移方程dp[i]=min{dp[j-1]+1|pal[j][i]==true}。
参考代码
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
using namespace std;
const int maxn = 1005;
int dp[maxn]; //dp[i]表示到i位置至少需要分成多少个回文串
bool pal[maxn][maxn];
int main(){
int cas;
cin >> cas;
while(cas--){
string s;
cin >> s;
memset(pal,false,sizeof(pal));
memset(dp,0,sizeof(dp));
pal[0][0]=true;
for(int i=1; i<s.size(); i++){
int j=0;
while(j+i<s.size()&&i-j>=0&&s[i-j]==s[i+j]){
pal[i-j][i+j]=true;
j++;
}
j=0;
while(i-1-j>=0&&i+j<s.size()&&s[i-1-j]==s[i+j]){
pal[i-1-j][i+j]=true;
j++;
}
}
for(int i=0; i<s.size(); i++) dp[i] = i+1;
for(int i=1; i<s.size(); i++){
for(int j=0; j<=i; j++){
if(pal[j][i]){
if(j==0)
dp[i]=1;
else
dp[i]=min(dp[i],dp[j-1]+1);
}
}
}
printf("%d\n",dp[s.size()-1]);
}
}