BZOJ3790:神奇项链(Manacher)

Description

母亲节就要到了,小 H 准备送给她一个特殊的项链。这个项链可以看作一个用小写字
母组成的字符串,每个小写字母表示一种颜色。为了制作这个项链,小 H 购买了两个机器。第一个机器可以生成所有形式的回文串,第二个机器可以把两个回文串连接起来,而且第二个机器还有一个特殊的性质:假如一个字符串的后缀和一个字符串的前缀是完全相同的,那么可以将这个重复部分重叠。例如:aba和aca连接起来,可以生成串abaaca或 abaca。现在给出目标项链的样式,询问你需要使用第二个机器多少次才能生成这个特殊的项链。 

Input

输入数据有多行,每行一个字符串,表示目标项链的样式。 

Output

多行,每行一个答案表示最少需要使用第二个机器的次数。 

Sample Input

abcdcba
abacada
abcdef

Sample Output

0
2
5

HINT

每个测试数据,输入不超过 5行
每行的字符串长度小于等于 50000

Solution

先manacher求出len数组
然后问题就可以转化成线段区间完全覆盖问题
贪心就可以了

Code

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<algorithm>
 5 #define N (100000+1000)
 6 using namespace std;
 7 
 8 struct Node{int x,y;}L[N];
 9 bool cmp(Node a,Node b){return a.x<b.x;}
10 int n,tot,len[N];
11 char a[N],s[N];
12 
13 void Manacher()
14 {
15     int x,mid=0,maxn=0;
16     for (int i=1; i<=tot; ++i)
17     {
18         if (i>maxn) x=1;
19         else x=min(maxn-i+1,len[mid*2-i]);
20         while (s[i+x]==s[i-x]) ++x;
21         len[i]=x;
22         if (i+x-1>maxn) maxn=i+x-1,mid=i;
23     }
24 }
25 
26 int main()
27 {
28     while (scanf("%s",a)!=EOF)
29     {
30         n=strlen(a);
31         tot=0;
32         s[++tot]='@'; s[++tot]='#';
33         for (int i=0; i<n; ++i)
34             s[++tot]=a[i], s[++tot]='#';
35         s[++tot]='$';
36         Manacher();
37         
38         int cnt=0;
39         for (int i=2; i<tot; ++i)
40             L[++cnt].x=i-len[i]+1, L[cnt].y=i+len[i]-1;
41         
42         sort(L+1,L+cnt+1,cmp);
43         int p=1,now=1,ans=0;
44         while (now<tot-1)
45         {
46             int maxn=-1;
47             while (p<=tot && L[p].x<=now+1) maxn=max(maxn,L[p].y),p++;
48             now=maxn; ans++;
49         }
50         printf("%d\n",ans-1);
51     }
52 }
posted @ 2018-08-08 21:16  Refun  阅读(225)  评论(0编辑  收藏  举报