Period (KMP 循环节)

Period

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 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

题目翻译:

对于具有N个字符的给定字符串S的每个前缀(每个字符具有介于97和126之间的ASCII代码),我们想知道前缀是否是周期性字符串。也就是说,对于每个i(2 <= i <= N),我们想要知道最大的K> 1(如果有的话),使得长度为i的S的前缀可以写为AK,即A级联K时间,对于一些字符串A.当然,我们也想知道时期K.
输入
输入文件由几个测试用例组成。每个测试用例包含两行。第一行包含N(2 <= N <= 1 000 000) - 字符串S的大小。第二行包含字符串S.输入文件以一行结尾,数字为零。
产量
对于每个测试用例,在一行输出“测试用例#”和连续测试用例编号;然后,对于具有周期K> 1的长度为i的每个前缀,输出前缀大小i和由单个空格分隔的周期K;前缀大小必须按递增顺序排列。在每个测试用例后打印一个空行。

代码:
 

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define N 1000005
int n,nex[N];
char s[N];
void getnext()
{
    int k=-1,j=0;
    nex[0]=-1;
    while(j<n)
    {
        if(k==-1||s[j]==s[k]) nex[++j]=++k;
        else k=nex[k];
    }
}
int main()
{
    int t=1;
    while(~scanf("%d",&n)&&n)
    {
        scanf("%s",s);
        getnext();
        printf("Test case #%d\n",t++);
        for(int i=1;i<=n;i++)
        {
            int k=i-nex[i];
            if(i%k==0&&i/k>1)
                printf("%d %d\n",i,i/k);
        }
        printf("\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/chimchim04/article/details/81533371