POJ - 1961 Period KMP

传送门:点击打开链接

题意就是寻找一个字符串前缀的最短循环节,从而求出最大循环数。利用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;
}


发布了173 篇原创文章 · 获赞 28 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/ECNU_LZJ/article/details/77451255