码迷,mamicode.com
首页 > 其他好文 > 详细

hdu1358 KMP求字符串最小循环节

时间:2014-10-19 21:09:09      阅读:195      评论:0      收藏:0      [点我收藏+]

标签:style   blog   color   io   ar   for   sp   div   on   

对于一个字符串S,长度为L,如果由长度为len的字符串s(字符串s的最小循环节是其本身)循环k次构成,那么字符串s就是字符串S的最小循环节

那么字符串有个很重要的性质和KMP挂钩,即  i - next[i] 为字符串s的长度 i%(i - next[i]) ==0

证明:字符串S由s循环k次构成,那么有S[0-->L-len-1] == S[len-->L-1],即前k-1个循环节和后k-1个循环节构成的字符串相等

那么此时KMP数组的next[L] = k-1个循环节的长度, 也即 next[L] = L-len-1+1 = L - len,那么此时 L - next[L] = len , 所以 L % len = 0,   L % len = k

所以如果字符串存在循环节,那么i % (i - next[i]) ==0,循环节的长度为 i % ( i - next[i])

否则,循环节的为字符串本身。

 

 1 #include <stdio.h>
 2 #include <string.h>
 3 const int N = 1000000 + 10;
 4 char str[N];
 5 int next[N];
 6 void makeNext(char *str)
 7 {
 8     int i=0,j=-1;
 9     next[0] = -1;
10     while(str[i])
11     {
12         if(j==-1||str[i]==str[j])
13         {
14             i++;
15             j++;
16             next[i] = j;
17         }
18         else
19             j = next[j];
20     }
21 }
22 int main()
23 {
24     
25     int n;
26     int tCase = 1;
27     while(true)
28     {
29         scanf("%d",&n);
30         if(n==0)
31             break;
32         scanf("%s",str);
33         makeNext(str);
34         printf("Test case #%d\n",tCase++);
35         for(int i=2; i<=n; ++i)
36         {
37             if(i%(i-next[i])==0 && next[i]!=0)//next[i]!=0,如果为0,循环节是本身
38                 printf("%d %d\n",i,i/(i-next[i]));
39             
40         }
41         puts("");
42         
43     }
44     return 0;
45 }

 

hdu1358 KMP求字符串最小循环节

标签:style   blog   color   io   ar   for   sp   div   on   

原文地址:http://www.cnblogs.com/justPassBy/p/4035361.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!