Poj 1961 Period
Posted wawawa8
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Poj 1961 Period相关的知识,希望对你有一定的参考价值。
题面
http://poj.org/problem?id=1961
题解
发现一个性质 一个循环的串 假设循环节长度为L 那么我们取其前size-L位,后size-L位,这两个串相同
相对应的,如果一个长度为size的串,我们取前k位,和后k位相同 那么size-k一定是这个串的循环节
所以我们只要对于每一位 找到前i位的子串的最长的前缀与对应长度的后缀相同的长度 那么i-length一定是答案
最长前缀=后缀 我们不难想到kmp的next数组
所以做一下kmp 求得next数组就做完了
复杂度$O(n)$
Code
1 #include<iostream> 2 #include<cstdlib> 3 #include<cstdio> 4 using namespace std; 5 typedef long long ll; 6 7 ll read(){ 8 ll x=0,f=1;char c=getchar(); 9 while(c<‘0‘ || c>‘9‘){if(c==‘-‘)f=-1;c=getchar();} 10 while(c>=‘0‘ && c<=‘9‘){x=x*10+c-‘0‘;c=getchar();} 11 return x*f; 12 } 13 14 int n; 15 char s[1000100]; 16 int nxt[1000100]; 17 18 int main(){ 19 #ifdef LZT 20 freopen("in","r",stdin); 21 #endif 22 int tc=0; 23 while(1){ 24 n=read(); 25 if(!n) break; 26 scanf("%s",&s); 27 nxt[0]=0,nxt[1]=0; 28 for(int i=1;i<n;i++){ 29 int j=nxt[i]; 30 while(j && s[i]!=s[j]) j=nxt[j]; 31 nxt[i+1]=(s[i]==s[j])?j+1:0; 32 } 33 printf("Test case #%d ",++tc); 34 for(int i=1;i<=n;i++){ 35 if(i%(i-nxt[i])==0 && nxt[i]){ 36 printf("%d %d ",i,i/(i-nxt[i])); 37 } 38 } 39 puts(""); 40 } 41 return 0; 42 }
Review
动机?
kmp的一个功能就是处理循环串
这算是个模板题?
以上是关于Poj 1961 Period的主要内容,如果未能解决你的问题,请参考以下文章