基准时间限制: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硬生生把自己写到爆炸。
dp[i]表示以i结尾的划分数量的最小值,dp[i]=min(dp[i],dp[j]+1) 当j<i且从j到i是一个回文串时。
代码:
#pragma warning(disable:4996)
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <string>
#include <cstring>
using namespace std;
int len;
char s[5005];
char s1[5005];
int dp[5005];
int v[5005][5005];
void input()
{
scanf("%s", s1);
len = strlen(s1);
strcpy(s + 1, s1);
}
void solve()
{
int i, j;
for (i = 0; i <= len; i++)
{
v[i][i] = 1;
}
for (i = 1; i <= len; i++)
{
dp[i] = i;
for (j = i; j >= 1; j--)
{
if (i == j)
{
dp[i] = min(dp[i], dp[i - 1] + 1);
}
else if (i - j == 1 && s[i] == s[j])
{
v[j][i] = 1;
dp[i] = min(dp[i], dp[j-1] + 1);
}
else if (v[j + 1][i - 1]&&s[i]==s[j])
{
v[j][i] = 1;
dp[i] = min(dp[i], dp[j-1] + 1);
}
}
}
printf("%d", dp[len]);
}
int main()
{
//freopen("i.txt", "r", stdin);
//freopen("o.txt", "w", stdout);
input();
solve();
//system("pause");
return 0;
}