Bzoj1511---OKR-Periods of Words(KMP)
大意:对于给定串的每个前缀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~~~