您的位置:首页 > 其它

POJ - 1961 Period KMP

2017-08-21 16:27 453 查看
传送门:点击打开链接

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

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  POJ 1961 Period KMP