神奇項鍊(manacher)
阿新 • • 發佈:2020-07-23
神奇項鍊
描述
母親節就要到了,小 H 準備送給她一個特殊的項鍊。這個項鍊可以看作一個用小寫字母組成的字串,每個小寫字母表示一種顏色。為了製作這個項鍊,小 H 購買了兩個機器。第一個機器可以生成所有形式的迴文串,第二個機器可以把兩個迴文串連線起來,而且第二個機器還有一個特殊的性質:假如一個字串的字尾和一個字串的字首是完全相同的,那麼可以將這個重複部分重疊。例如:aba和aca連線起來,可以生成串abaaca或 abaca。現在給出目標項鍊的樣式,詢問你需要使用第二個機器多少次才能生成這個特殊的項鍊。
輸入
輸入資料有多行,每行一個字串,表示目標項鍊的樣式。
每個測試資料,輸入不超過 5行
輸出
多行,每行一個答案表示最少需要使用第二個機器的次數。
樣例
輸入
abcdcba abacada abcdef
輸出
0 2 5
1 #include<bits/stdc++.h> 2 using namespace std; 3 char s[1000001],s_new[3000000]; 4 int p[3000000]; 5 struct data{ 6 int l,r; 7 }a[10000001]; 8 bool cmp(data x,data y) 9 { 10 if(x.l==y.l) 11 returnx.r>y.r; 12 else 13 return x.l<y.l; 14 } 15 int get() 16 { 17 s_new[0]='$'; 18 s_new[1]='#'; 19 int k=2; 20 int len=strlen(s); 21 for(int i=0;i<len;i++) 22 { 23 s_new[k++]=s[i]; 24 s_new[k++]='#'; 25 } 26 s_new[k]='\0'; 27 return k; 28} 29 int manacher() 30 { 31 int len=get(); 32 int id=0,mx=0; 33 for(int i=1;i<len;i++) 34 { 35 if(i<mx) 36 p[i]=min(mx-i,p[2*id-i]); 37 else 38 p[i]=1; 39 while(s_new[i-p[i]]==s_new[i+p[i]]) 40 p[i]++; 41 if(mx<i+p[i]) 42 { 43 id=i; 44 mx=i+p[i]; 45 } 46 a[i].l=i-p[i]+1,a[i].r=i+p[i]-1; 47 } 48 sort(a+1,a+len,cmp); 49 int ans=0,q=0,i=1; 50 while(i<len) 51 { 52 int sum=0; 53 while(a[i].l-1<=q) 54 { 55 sum=max(sum,a[i].r); 56 i++; 57 } 58 ans++; 59 q=sum; 60 if(q==len-1) 61 break; 62 } 63 return ans-1; 64 } 65 int main() 66 { 67 while(scanf("%s",s)!=EOF) 68 printf("%d\n",manacher()); 69 return 0; 70 }