POJ

来源:互联网 发布:淘宝上怎么买身份证 编辑:程序博客网 时间:2024/06/07 05:53

传送门:点击打开链接

题意就是寻找一个字符串前缀的最短循环节,从而求出最大循环数。利用KMP算法可以求出Next数组,然后根据Next数组的定义,我们可以知道对于一个前缀S

1.如果i % (i - Next[i]) == 0,则S是有循环节的,循环节长度为i - Next[i]。

2.因为Next[i]表示最长前后缀,所以i - Next[i]是最短循环节。

3.Next[i]不能为0,否则就表示S循环节是其自身。

代码如下:

#include <cstring>#include <cstdlib>#include <cstdio>using namespace std;const int N = 1000005;char T[N];int lent;int Next[N];void getNext(){    int i = 0;    int k = -1;    Next[0] = -1;    while (i < lent)        if (k == -1 || T[i] == T[k])            Next[++i] = ++k;        else            k = Next[k];}int main(){    //freopen("test.txt", "r", stdin);    //freopen("out.txt", "w", stdout);    int Case = 1;    while (~scanf("%d", &lent) && lent)    {        scanf("%s", T);        lent = strlen(T);        getNext();        printf("Test case #%d\n", Case++);        for(int i = 1; i <= lent; i++)        {            /*            如果i % (i - Next[i]) == 0满足,则i - Next[i]为循环节长度。            但是循环节长度又不能是总长度,所以Next[i] != 0。            */            if (i % (i - Next[i]) == 0 && Next[i])                printf("%d %d\n", i, i / (i - Next[i]));        }        printf("\n");    }    return 0;}


原创粉丝点击