有一个字符串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;
}
				
			 
    				 rockdu
			
			rockdu
	
			
				 
				
				 
	
没有帐号? 立即注册