1154 回文串划分(DP+Manacher)

基准时间限制: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
相关问题
最长回文子串 V2(Manacher算法) 最长回文子串  回文串划分 V2 6
40 
回文字符串 10
 
 
 
//显然dp,dp[i] 表前 i 个数最少能变几个回文
dp[i] = min(dp[i], dp[z-1]+1)   "s[z],s[z+1]...s[i]" 是一个回文串
用马拉车就是 n*2n ,5000*10000,话说弱鸡我debug一万年。。。
不用就是 n^3 吧,不大懂
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define LL long long
 4 #define MOD 1000000007
 5 #define MX 5005
 6 
 7 int n;
 8 int len;
 9 char temp[MX];
10 char str[MX*2];
11 int p[MX*2];
12 int dp[MX*2];
13 
14 void Init()
15 {
16     len = 0;
17     str[len++]='@';
18     str[len++]='#';
19     n = strlen(temp);
20     for (int i=0;i<n;i++)
21     {
22         str[len++]=temp[i];
23         str[len++]='#';
24     }
25     memset(p,0,sizeof(p));
26 }
27 
28 void Manacher()
29 {
30     Init();
31     int mx = 0, id =0;
32     for (int i=1;i<len;i++)
33     {
34         p[i] = mx>i ? min(p[2*id-i],mx-i):1;
35         while (str[i+p[i]]==str[i-p[i]]) p[i]++;
36         if (i+p[i]>mx)
37         {
38             mx = i+p[i];
39             id = i;
40         }
41     }
42 }
43 
44 int main()
45 {
46     while (scanf("%s",temp)!=EOF)
47     {
48         Manacher();
49 
50         for (int i=0;i<n;i++)
51         {
52             dp[i] = i+1; //初值
53             int pos = (i+1)*2;
54             for (int j=pos;j>=1;j--)
55             {
56                 if(j+p[j]-2>=pos)
57                 {
58                     int pre = (j-(pos-j))/2-1;
59                     if (pre==0) dp[i]=1;
60                     else dp[i]= min(dp[pre-1]+1,dp[i]);
61                 }
62             }
63         }
64         printf("%d
",dp[n-1]);
65     }
66     return 0;
67 }
View Code
原文地址:https://www.cnblogs.com/haoabcd2010/p/7638295.html