BZOJ3790:神奇项链(Manacher)
Description
母亲节就要到了,小 H 准备送给她一个特殊的项链。这个项链可以看作一个用小写字
母组成的字符串,每个小写字母表示一种颜色。为了制作这个项链,小 H 购买了两个机器。第一个机器可以生成所有形式的回文串,第二个机器可以把两个回文串连接起来,而且第二个机器还有一个特殊的性质:假如一个字符串的后缀和一个字符串的前缀是完全相同的,那么可以将这个重复部分重叠。例如:aba和aca连接起来,可以生成串abaaca或 abaca。现在给出目标项链的样式,询问你需要使用第二个机器多少次才能生成这个特殊的项链。
Input
输入数据有多行,每行一个字符串,表示目标项链的样式。
Output
多行,每行一个答案表示最少需要使用第二个机器的次数。
Sample Input
abcdcba
abacada
abcdef
abacada
abcdef
Sample Output
0
2
5
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 }