【题目大意】
把一个字符串切割成尽量少的回文串。
【题目分析】
很裸的dp,f[i]=min(f[i],f[j]+1(i..j是回文串)).
如果这样写的话,加入判断,n^3.
倘若加入预处理就是2*n^2. 大约在20~30ms之间
我看到了一些10ms的代码,他们把动态规划和预处理合在一起进行。
给一个virtual judge 的链接。代码在这里
然后就是我的方法,用manacher进行处理,就变成了n+n^2。理论上是比上一种方法好的
【代码】
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int r[2010],dp[2010];
char s[2010],ch[2010];
inline int min(int a,int b)
{return a>b?b:a;}
inline bool pd(int l,int e)
{
if ((r[l+e]*2-1)/2>=e-l+1) return true;
else return false;
}
int main()
{
int tt;
scanf("%d",&tt);
while (tt--)
{
memset(r,0,sizeof r);
memset(dp,0x3f,sizeof dp);
memset(r,0,sizeof r);
dp[0]=0;
scanf("%s",ch+1);
int l=strlen(ch+1);
s[1]='#';s[2*l+2]='#';
for (int i=1;i<=l;++i)
{
s[i*2]=ch[i];
s[i*2|1]='#';
}
int id=0,mx=0;
r[0]=1;
for (int i=1;i<=2*l+1;++i){
if (mx>i) r[i]=min(r[2*id-i],mx-i);
else r[i]=1;
while (s[i-r[i]]==s[i+r[i]]) r[i]++;
if (i+r[i]>mx) mx=i+r[i],id=i;
}
for (int i=1;i<=l;++i)
for (int j=1;j<=i;++j)
if (pd(j,i)) dp[i]=min(dp[i],dp[j-1]+1);
printf("%d\n",dp[l]);
}
}