基准时间限制:1 秒 空间限制:131072 KB 分值: 40
难度:4级算法题
有一个字符串S,求S最少可以被划分为多少个回文串。
例如:abbaabaa,有多种划分方式。
a|bb|aabaa - 3 个回文串
a|bb|a|aba|a - 5 个回文串
a|b|b|a|a|b|a|a - 8 个回文串
其中第1种划分方式的划分数量最少。
Input
输入字符串S(S的长度<= 5000)。
Output
输出最少的划分数量。
Input示例
abbaabaa
Output示例
3
用dp[ i ]数组表示到第i个字符,构成最少回文串的个数,dp[ i ]初始化为i。
然后从1~i遍历(我的字符串是从1开始存的),状态转移方程为:
dp[ i ] = min(dp[ i ] , dp [ j - 1] + 1);如果从j到i可以构成一个回文串了,这个dp就用状态转移方程更新一次。
代码如下:
#include <stdio.h>
#include <cstring>
#include <algorithm>
using namespace std;
#define CLR(a,b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define LL long long
int main()
{
int dp[5011];
char str[5011];
scanf ("%s",str+1);
str[0] = '@';
int l = strlen(str);
dp[0] = 0;
dp[1] = 1;
for (int i = 2 ; i < l ; i++)
{
dp[i] = i + 1;
for (int j = 1 ; j <= i ; j++)
{
bool flag = true; //从j到i是否是回文串
int st = j;
int endd = i;
while (endd >= st)
{
if (str[endd] != str[st])
{
flag = false;
break;
}
endd--;
st++;
}
if (flag)
dp[i] = min (dp[i] , dp[j-1] + 1);
}
}
printf ("%d\n",dp[l-1]);
return 0;
}