E - Period HDU-1358

题目大意:

     多组。给一个n,输入长度为n 的串,求:这个串所有存在循环节的前缀,输出前缀长度和循环次数(不重叠)。

解题思路:

    从i=0开始,判断前缀是不是存在循环节,即(i+1)%(i-next[i]) 是否==0 。注:next[i]值是0或-1的忽略,说明前面不存在任何循环节。(关于循环节解释的见《KMP 专题知识》)。

参考代码:

 1 #include <iostream>
 2 #include <stdio.h>
 3 using namespace std;
 4 char a[1000010];
 5 int next[1000010];
 6 int n;
 7 void GetNext()    //获得a数列的next数组
 8 {
 9     int i=0,k=-1;
10     next[0] = -1;
11     while(i<n){
12         if(k==-1){
13             next[i+1] = 0;
14             i++;k++;
15         }
16         else if(a[i]==a[k]){
17             next[i+1] = k+1;
18             i++;k++;
19         }
20         else
21             k = next[k];
22     }
23 }
24 void DisRes(int num)
25 {
26     int j;
27     printf("Test case #%d\n",num);
28     for(int i=0;i<=n;i++)
29     {
30         if(next[i]==-1 || next[i]==0)   //next[i]是-1或0的忽略,说明之前没有周期性前缀
31             continue;
32         j = i - next[i];
33         if(i%j==0)  //能整除,说明存在周期性前缀
34             printf("%d %d\n",i,i/j);    //输出这个前缀的长度和周期数
35     }
36     printf("\n");
37 }
38 int main()
39 {
40     int num = 0;
41     while(scanf("%d",&n)!=EOF)
42    {
43         if(n==0) break;
44         scanf("%s",a);
45         GetNext();  //获得next[]数组
46         DisRes(++num);  //输出结果
47     }
48     return 0;
49 }
这个回头自己写过

 

    

 

posted @ 2017-09-14 20:19  小可爱的小可爱  阅读(152)  评论(0编辑  收藏  举报