输入一个由小写字母组成的字符串,你的任务是把它划分成尽量少的回文串。例如,racecar本身就是回文串;fastcar只能分成7个单字母的回文串,aaadbccb最少分成3个回文串:aaa,d,bccb。字符串的长度不超过1000.
分析:d[i]为字符0~i划分成的最小回文串的个数,则d[i]=min{d[j]+1|s[j+1~i]是回文串}。可以先用O(n^2)时间预处理s[i...j]是否为回文串。方法是枚举中心,然后不断向左右延伸并且标记当前子串是回文串,直到延伸的左右字符不同为止。这样一来,每次转移的时间降为了O(1),总时间复杂度为O(n^2)。
#include <iostream>
#include <cstring>
using namespace std;
const int maxn = 1010;
int dp[maxn],s[maxn][maxn];
char str[maxn];
void init(int n){
for(int i=1;i<=n;i++){
int l=i,r=i;
while(l>=0&&str[l]==str[r]){
s[l][r]=1;
l--,r++;
}
l=i,r=i+1;
while(l>=0&&str[l]==str[r]){
s[l][r]=1;
l--,r++;
}
}
}
int main(){
//freopen("1.txt","r",stdin);
scanf("%s",str+1);
int n=strlen(str+1);
init(n);
for(int i=1;i<=n;i++){
dp[i]=i;
for(int j=0;j<i;j++){
if(s[j+1][i]){
dp[i]=min(dp[i],dp[j]+1);
}
}
}
printf("%d",dp[n]);
return 0;
}