1. 程式人生 > >Bzoj1511---OKR-Periods of Words(KMP)

Bzoj1511---OKR-Periods of Words(KMP)

技術分享 scanf 前綴 main tps () int 統計 oid

(傳送門)

技術分享圖片

大意:對於給定串的每個前綴i,求最長的,使這個字符串重復兩邊能覆蓋原前綴i的前綴(就是前綴i的一個前綴),求所有的這些“前綴的前綴”的長度和

利用 p 的性質:前綴 i 的長度為 p[i] 的前綴和後綴是相等的

這說明:如果i有一個公共前後綴長度為j,那麽這個前綴i就有一個周期為i-j

於是我們先預處理p數組,然後再把p數組更新變成最小公共前後綴。最後跑一遍統計答案即可。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<cstring>
 5
#include<algorithm> 6 #include<cstdlib> 7 using namespace std; 8 int p[2000005],n; 9 char st[2000005]; 10 void pre() 11 { 12 p[0]=0; int j=0; 13 for (int i=1; i<=n; i++){ 14 while (j>0 && st[j+1]!=st[i+1]) j=p[j]; 15 if (st[j+1]==st[i+1]) j++; 16 p[i+1
]=j; 17 } 18 } 19 int main() 20 { 21 scanf("%d\n",&n); 22 cin>>st+1; 23 pre(); 24 int ans=0; 25 for (int i=1; i<=n; i++){ 26 if (!p[i]) continue; 27 if (p[p[i]]) p[i]=p[p[i]]; 28 } 29 for (int i=1; i<=n; i++) if (p[i])ans+=i-p[i];
30 cout<<ans<<endl; 31 return 0; 32 }

miao~~~

Bzoj1511---OKR-Periods of Words(KMP)