HDU - 1358 - Period
先上题目:
Period
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 2061 Accepted Submission(s): 1016
Problem Description
For
each prefix of a given string S with N characters (each character has
an ASCII code between 97 and 126, inclusive), we want to know whether
the prefix is a periodic string. That is, for each i (2 <= i <= N)
we want to know the largest K > 1 (if there is one) such that the
prefix of S with length i can be written as AK , that is A concatenated K times, for some string A. Of course, we also want to know the period K.
Input
The
input file consists of several test cases. Each test case consists of
two lines. The first one contains N (2 <= N <= 1 000 000) – the
size of the string S. The second line contains the string S. The input
file ends with a line, having the number zero on it.
Output
For
each test case, output “Test case #” and the consecutive test case
number on a single line; then, for each prefix with length i that has a
period K > 1, output the prefix size i and the period K separated by a
single space; the prefix sizes must be in increasing order. Print a
blank line after each test case.
Sample Input
3
aaa
12
aabaabaabaab
0
Sample Output
Test case #1
2 2
3 3
Test case #2
2 2
6 2
9 3
12 4
题意是这样的:给你一个字符串,问你对于他的每一个长度不等于1前缀,能否把这个前缀变成有一个循环节循环不止1次得到,如果有,输出这个前缀的循环节的长度以及循环节循环的次数。
这题需要用到kmp的next数组,假设字符串有0开始保存,这个字符串的长度为len,则这个字符串的是否有多个循环节构成
只要判断 len%(len-next[len])==0? 判断成立就说明可以。否则就不可以。
如果可以,那么循环节的长度就是len/(len-next[len])。
注意这里虽然由0单位开始保存字符串,但是len是指这个字符串的长度。
字符串都东西现在还不是很明白。总之还需要努力。
这一题还有一个坑就是格式,不止是每一个case之间要有一个blank,结尾的那个case的后面也要有一个blank。= =
上代码:
1 #include <cstdio> 2 #include <cstring> 3 #define MAX 1000100 4 using namespace std; 5 6 char s[MAX]; 7 int next[MAX],n; 8 9 void get_next() 10 { 11 int i,k; 12 i=0; 13 k=-1; 14 memset(next,-1,sizeof(next)); 15 while(i<n) 16 { 17 if(k==-1 || s[i]==s[k]){i++;k++;next[i]=k;} 18 else k=next[k]; 19 } 20 } 21 22 int main() 23 { 24 int t,i; 25 t=1; 26 //freopen("data.txt","r",stdin); 27 while(scanf("%d",&n),n) 28 { 29 scanf("%s",s); 30 get_next(); 31 printf("Test case #%d\n",t++); 32 for(i=1;i<n;) 33 { 34 i++; 35 int temp=i-next[i]; 36 if(i>temp && i%temp==0) printf("%d %d\n",i,i/temp); 37 } 38 printf("\n"); 39 } 40 return 0; 41 }