1. 程式人生 > >bzoj3790 神奇項鏈

bzoj3790 神奇項鏈

字符串 turn script bzoj template 等於 ans can memset

Description

母親節就要到了,小 H 準備送給她一個特殊的項鏈。這個項鏈可以看作一個用小寫字 母組成的字符串,每個小寫字母表示一種顏色。為了制作這個項鏈,小 H 購買了兩個機器。第一個機器可以生成所有形式的回文串,第二個機器可以把兩個回文串連接起來,而且第二個機器還有一個特殊的性質:假如一個字符串的後綴和一個字符串的前綴是完全相同的,那麽可以將這個重復部分重疊。例如:aba和aca連接起來,可以生成串abaaca或 abaca。現在給出目標項鏈的樣式,詢問你需要使用第二個機器多少次才能生成這個特殊的項鏈。

Input

輸入數據有多行,每行一個字符串,表示目標項鏈的樣式。

Output

多行,每行一個答案表示最少需要使用第二個機器的次數。

Sample Input

abcdcba
abacada
abcdef

Sample Output

0
2
5

Hint

每個測試數據,輸入不超過 5行 每行的字符串長度小於等於 50000
manacher+貪心 manacher:一種線性時間求回文串長度的算法(右轉Baidu) 用manacher處理出以某個點開始的最長回文串長度,問題就轉變成區間覆蓋問題。 用貪心跑一遍即可。
#include<iostream>
#include<cstdio>
#include
<cstring> #include<cctype> using namespace std; template <typename T> inline T min(T &a,T &b) {return a<b ?a:b;} template <typename T> inline T max(T &a,T &b) {return a>b ?a:b;} char a[1000005],b[1000005]; int p[1000005],f[1000005]; int main(){ while(scanf("%s",a)!=EOF){ memset(f,
0,sizeof(f)); int len=strlen(a),n=0,id=0,mx=-1,last,mxd,ans=0; for(int i=0;i<len;++i) b[n++]=#,b[n++]=a[i]; b[n++]=#; for(int i=0;i<n;++i){ if(i<mx) p[i]=min(p[id*2-i],mx-i+1); else p[i]=1; while(i-p[i]>=0&&i+p[i]<n&&b[i-p[i]]==b[i+p[i]]) ++p[i]; if(i+p[i]-1>mx) mx=i+p[i]-1,id=i; f[i-p[i]+1]=i+p[i]-1; //處理出從點i-p[i]+1開始的最長回文串長度 }last=mxd=f[0]+2; for(int i=0;i<n;i+=2){ //貪心 if(i==last) last=mxd,++ans; mxd=max(mxd,f[i]+2); }printf("%d\n",ans); }return 0; }

bzoj3790 神奇項鏈