题意:
给一个字符串, 要求把它分割成若干个子串,使得每个子串都是回文串。问最少可以分割成多少个 ?
思路:不难想到,d【i】:表示以i结尾最少可以分几个字符串。d【i】= min(d【i】,d【j】+1)(j<i && s[j+1]~s[i]位回文串)。
这样的复杂度是O(n^3), 可以预处理出s的所有回文串(o(n^2))
这样就把复杂度降为o(n^2)。
预处理方法:枚举回文中心(有两种情况都考虑一下即可)。
#include<iostream>
#include<algorithm>
#include<string>
#include<cmath>
#include<vector>
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
const int maxn = 1e3 + 10;
char s[maxn];
int dp[maxn];
bool ok[maxn][maxn];
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
s[0] = '\0';
memset (ok, false, sizeof(ok));
scanf("%s", s+1);
memset(dp, 0, sizeof(dp));
int len = strlen(s+1);
for(int i = 1 ; i <= len ; i++)
{
for(int k = 0; (i-k) >= 1 && (i+k) <= len; k++)
{
if(s[i-k] == s[i+k])
ok[i-k][i+k]=1;
else
break;
}
if(s[i] == s[i+1])
{
for(int k = 0; (i-k) >= 1 && (i+k+1)<=len; k++)
{
if(s[i-k] == s[i+k+1])
ok[i-k][i+k+1] = 1;
else
break;
}
}
}
dp[0] = 0;
dp[1] = 1;
for(int i = 2; i <= len; i++)
{
dp[i] = i;
for(int j = 1; j <= i; j++)
{
if(ok[j][i])
dp[i] = min(dp[i], dp[j-1]+1);
}
}
printf("%d\n", dp[len]);
}
return 0;
}