Period (next与循环串)

来源:互联网 发布:oracle删除重复数据 编辑:程序博客网 时间:2024/06/14 08:07
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 A K,that is A concatenated K times, for some string A. Of course, we also want to know the period K.
Input
The input 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
3aaa12aabaabaabaab0
Sample Output
Test case #12 23 3Test case #22 26 29 3

12 4

题目大意:给出一个长度为n的字符串,从长度为2的前缀开始,一一判断 前缀 是否为 循环串 构成,并输出 前缀长度 和 循环串的个数 。

e.g Test case #2中 aabaabaab 是长度为9的前缀,其循环串为aab,个数为3,故输出 9 3 。

知识点:如果i,满足i%(i-next[i])=0则长度为i的前缀,是由循环串构成, 其个数为i/(i-next[i])。

Tip:但如此会出现循环串个数为1的情况,与题意不符,故排除掉。

抄袭加原创代码(抄袭部分出处未知):

#include<stdio.h>int next[1000005];char a[1000005];void getnext(char *a,int n){int i,j;i=0,j=next[0]=-1;while(i<n){if(j==-1||a[i]==a[j]){i++,j++;next[i]=j;}else{j=next[j];}}}int main(){int n,i,t=1;while(~scanf("%d",&n)&&n!=0){scanf("%s",a);printf("Test case #%d\n",t++);getnext(a,n);for(i=2;i<=n;i++){if(i%(i-next[i])==0&&i/(i-next[i])>1){printf("%d %d\n",i,i/(i-next[i]));}}printf("\n");}}