poj 2406 power strings

  题意:给一个字符串,求长度最短的循环节。

  题解:很经典的KMP的next数组的应用; 因为next数组代表模板串的最大公共前后缀,因此如果该字符串有循环节的话,那么从下标 next[len-1] 到 len-1 的这一段子串就代表了最短的循环节(不怎么明白的话可以求几个诸如abcabc、ababab 字符串的next数组出来研究下)。详见代码:

  

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <cmath>
 6 #include <set>
 7 #include <utility>
 8 #include <vector>
 9 #include <map>
10 #include <queue>
11 #include <stack>
12 const int inf=0x3f3f3f3f;
13 const double PI=acos(-1.0);
14 const double EPS=1e-8;
15 using namespace std;
16 typedef long long ll;
17 typedef pair<int,int> P;
18 
19 char str[1000005];
20 int next[1000005];
21 void makeNext()
22 {
23     int q,k;
24     int m=strlen(str);
25     next[0]=0;
26     k=0;
27     for(q=1; q<m; q++)
28     {
29         while(k>0&&str[q]!=str[k]) k=next[k-1];
30         if(str[k]==str[q]) k++;
31         next[q]=k;
32     }
33     //for(int i=0;i<=m;i++) printf("%d ",next[i]);
34 }
35 bool judge(int n)
36 {
37     int len=strlen(str);
38     if(len%n!=0) return false;
39     int cnt=len/n;
40     int t=0;
41     while(t<len)
42     {
43         for(int i=0,j=t;i<cnt;i++,j++)
44             if(str[i]!=str[j]) return false;
45         t+=cnt;
46     }
47     return true;
48 }
49 //
50 int main()
51 {
52     //freopen("test.txt","r",stdin);
53     while(scanf("%s",str)!=EOF)
54     {
55         int len=strlen(str);
56         if(len==1&&str[0]=='.') break;
57         makeNext();
58         //
59         if((len-next[len-1])&&len%(len-next[len-1])==0) //len-next[len-1]得到一个循环节的长度
60             printf("%d\n",len/(len-next[len-1]));
61         else 
62             printf("1\n");
63         /*
64         
65         一开始的蠢做法=_=...
66         int len=strlen(str);
67         len--;
68         int ans=1;
69         while(next[len]) ans++,len=next[len]-1;//得出有多少个循环节
70         if(judge(ans)) printf("%d\n",ans); //judge()判断长度为len/ans的循环节是否可行
71         else printf("1\n");
72         */
73     }
74     return 0;
75 }

 

posted @ 2017-05-03 13:31  爱喝可乐的咖啡  阅读(155)  评论(0编辑  收藏  举报