1511: [POI2006]OKR-Periods of Words
Description
一个串是有限个小写字符的序列,特别的,一个空序列也可以是一个串. 一个串P是串A的前缀, 当且仅当存在串B, 使得 A = PB. 如果 P A 并且 P 不是一个空串,那么我们说 P 是A的一个proper前缀. 定义Q 是A的周期, 当且仅当Q是A的一个proper 前缀并且A是QQ的前缀(不一定要是proper前缀). 比如串 abab 和 ababab 都是串abababa的周期. 串A的最大周期就是它最长的一个周期或者是一个空串(当A没有周期的时候), 比如说, ababab的最大周期是abab. 串abc的最大周期是空串. 给出一个串,求出它所有前缀的最大周期长度之和.
Input
第一行一个整数 k ( 1 k 1 000 000) 表示串的长度. 接下来一行表示给出的串.
Output
输出一个整数表示它所有前缀的最大周期长度之和.
Sample Input
8
babababa
babababa
Sample Output
24
这道题的最大周期像是一个类似于next数组一样的东西,不过next数组是最长的既是前缀又是后缀,这里显然是要求最短的既是前缀又是后缀,那么我们只需要不断令j=next[j]直到next[next[j]]等于0,这时next[j]就是最短的前缀,最长周期就是长度减最短的前缀,这样一次kmp就好了。。
1 #include<iostream> 2 #include<cstdlib> 3 #include<cmath> 4 #include<cstring> 5 #include<cstdio> 6 #include<algorithm> 7 #include<string> 8 #include<map> 9 #include<queue> 10 #include<vector> 11 #include<set> 12 #define inf 1000000000 13 #define maxn 1000000+5 14 #define maxm 10000+5 15 #define eps 1e-10 16 #define ll long long 17 #define for0(i,n) for(int i=0;i<=(n);i++) 18 #define for1(i,n) for(int i=1;i<=(n);i++) 19 #define for2(i,x,y) for(int i=(x);i<=(y);i++) 20 #define for3(i,x,y) for(int i=(x);i>=(y);i--) 21 #define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go) 22 using namespace std; 23 int read(){ 24 int x=0,f=1;char ch=getchar(); 25 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 26 while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();} 27 return x*f; 28 } 29 int n,next[maxn]; 30 char ch[maxn]; 31 int main(){ 32 //freopen("input.txt","r",stdin); 33 //freopen("output.txt","w",stdout); 34 int n=read(); 35 scanf("%s",ch+1); 36 for(int i=2,j=0;i<=n;i++){ 37 while(j&&ch[j+1]!=ch[i])j=next[j]; 38 if(ch[j+1]==ch[i])j++; 39 next[i]=j; 40 } 41 for1(i,n) 42 if(next[next[i]]) 43 next[i]=next[next[i]]; 44 ll ans=0; 45 for1(i,n) 46 if(next[i]) 47 ans+=(i-next[i]); 48 printf("%lld",ans); 49 return 0; 50 }