uvalive3026 Period (KMP+结论)

题目链接:http://vjudge.net/problem/viewProblem.action?id=29342

题目大意:给定字符串,找到每个前缀的最大循环节的个数。

首先当然是kmp预处理,接下来的问题是 怎么找循环节?

用反证法可以证明,如果f[i]~i之间的字符串能构成循环节,则该字符串就是i前缀对应的循环节,否则循环节不存在。

对每个前缀找到尾指针对应的失陪位置后,不需要按失陪指针继续往前寻找了(否则超时)。

只用判断上个位置到尾部的字符串是否是循环节(长度是否有整除关系),即知循环节个数。

代码奉上:

 1 #include <stdio.h>
 2 #include <algorithm>
 3 #include <stdlib.h>
 4 #include <cstring>
 5 
 6 int f[1000010];
 7 char p[1000010];
 8 void deal(int l){
 9     f[0]=-1;
10     int i=0,k=-1;
11     while(i<l){
12        if(k==-1 || p[k]==p[i])f[++i]=++k;
13        else k=f[k];
14     }
15     //for(i=0;i<l;i++)printf("%d: %d\n",i,f[i]);
16 }
17 int main(){
18    int n,cs=1;
19    while(scanf("%d",&n) && n){
20        scanf("%s",p);
21        deal(n);
22        printf("Test case #%d\n",cs++);
23        int i,k;
24        for(i=1;i<=n;i++){
25           if(f[i]==0 || i%(i-f[i]))continue;
26           k=i/(i-f[i]);
27           if(k>1)printf("%d %d\n",i,k);
28        }
29        printf("\n");
30        
31    }
32    return 0;
33 }
View Code

证明没有仔细说,不明白的欢迎留言讨论~

 

posted @ 2014-08-12 21:30  Ixia  阅读(230)  评论(0编辑  收藏  举报