首页 > 其他 > 详细

Poj 1961 Period

时间:2018-08-01 19:28:57      阅读:210      评论:0      收藏:0      [点我收藏+]

题面

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\n",++tc);
34         for(int i=1;i<=n;i++){
35             if(i%(i-nxt[i])==0 && nxt[i]){
36                 printf("%d %d\n",i,i/(i-nxt[i]));
37             }
38         }
39         puts("");
40     }
41     return 0;
42 }

Review

动机?

kmp的一个功能就是处理循环串

这算是个模板题?

Poj 1961 Period

原文:https://www.cnblogs.com/wawawa8/p/9403392.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!