题意
给一个字符串,如果这个串有一个长度为 i 的前缀,是由多个相同的子串(循环节)构成的,输出这样的 i 和子串循环的次数。
思路
这个题是对 next 数组含义的理解。
现在其实也没有理解得很透彻。
下面这些话恐怕只有现在的我能看懂。以“abc”为循环节试着把 next 打出来,就会清晰很多。
只有前缀是由完全相同的循环节构成时,j - next[j] 才会等于一个常数,这个常数就是循环节的长度。如果中间由一处断掉,next[j] 都会跳到之前的位置,j - next[j] 就会变得无规律可循了。
题目链接
http://poj.org/problem?id=1961
AC代码
#include<cstdio>
#include<iostream>
using namespace std;
const int maxm = 1e6 + 10;
int m;
char T[maxm];
int Next[maxm];
void get_next()
{
int j = 0, k = -1;
Next[0] = -1;
while(j < m)
{
if(k == -1 || T[j] == T[k]) Next[++ j] = ++ k;
else k = Next[k];
}
}
int main()
{
int cas = 0;
while(scanf("%d", &m) != EOF)
{
if(m == 0) break;
scanf(" %s", T);
get_next();
printf("Test case #%d\n", ++ cas);
for(int j= 0; j<= m; j ++) // <= , 耐人寻味
{
int d = j - Next[j];
if(j % d == 0 && j / d > 1) printf("%d %d\n", j, j / d); //关键所在
}
printf("\n");
}
return 0;
}