有一个字符串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输出最少的划分数量。Sample Input
abbaabaa
Sample Output
3
首先我们看见回文串问题可以模仿Manacher向空隙中填满'#'符号。然后可以推知DP转移方程dp[i + j] = min(dp[i + j], dp[i - j - 1] + 1) {0<=i<=len - 1, 0<=j<=min(i, n - i - 1), s[i + j] == s[i - j]} 然后就可以轻松以比较小的常数的O(N^2)过掉。AC code:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn = 5e3 + 5; int dp[maxn << 1], cnt; char s[maxn << 1], r[maxn << 1]; int main() { memset(dp, 0x3f, sizeof(dp)); gets(r); s[cnt++] = '#', dp[0] = 0; int len = strlen(r); for(register int i = 0; i < len; ++i) s[cnt++] = r[i], s[cnt++] = '#'; for(int i = 1; i < cnt; ++i) { int a = min(cnt - i - 1, i); for(register int j = 0; j <= a && s[i - j] == s[i + j]; ++j) dp[i + j] = min(dp[i + j], dp[i - j - 1] + 1); } printf("%d", dp[cnt - 2]); return 0; }
没有帐号? 立即注册