Description:

一个字符串的前缀是从第一个字符开始的连续若干个字符,例如”abaab”共有5个前缀,分别是a, ab, aba, abaa, abaab。

我们希望知道一个N位字符串S的前缀是否具有循环节。

换言之,对于每一个从头开始的长度为 i (i>1)的前缀,是否由重复出现的子串A组成,即 AAA…A (A重复出现K次,K>1)。

如果存在,请找出最短的循环节对应的K值(也就是这个前缀串的所有可能重复节中,最大的K值)。

输入格式

输入包括多组测试数据,每组测试数据包括两行。

第一行输入字符串S的长度N。

第二行输入字符串S。

输入数据以只包括一个0的行作为结尾。

输出格式

对于每组测试数据,第一行输出 “Test case #” 和测试数据的编号。

接下来的每一行,输出具有循环节的前缀的长度i和其对应K,中间用一个空格隔开。

前缀长度需要升序排列。

在每组测试数据的最后输出一个空行。

数据范围

2≤N≤1000000

输入样例:

3
aaa
4
abcd
12
aabaabaabaab
0

输出样例:

Test case #1
2 2
3 3

Test case #2

Test case #3
2 2
6 2
9 3
12 4

一个重要的性质 周期(KMP找最小循环节)_Test 为此字符串的最小循环节( 周期(KMP找最小循环节)_测试数据_02 为字符串的结尾),另外如果 周期(KMP找最小循环节)_字符串_03 ,此字符串的最小周期就为 周期(KMP找最小循环节)_字符串_04
所以直接对给出的串求出来 周期(KMP找最小循环节)_Test_05 数组,然后对每一个位置进行判断是否这个位置的 周期(KMP找最小循环节)_Test_05 数组不为 周期(KMP找最小循环节)_测试数据_07 并且 周期(KMP找最小循环节)_字符串_03

AC代码:

const int N = 2e6 + 50;

int n, k;
char a[N];

char p[N];
int m, nxt[N];

void GetNext(char *p, int n)
{
nxt[0] = nxt[1] = 0;
for (int i = 1; i < n; i++)
{
int j = nxt[i];
while (j && p[i] != p[j])
j = nxt[j];
nxt[i + 1] = (p[i] == p[j]) ? j + 1 : 0;
}
}

int main()
{
int cas = 1;
while (cin >> n)
{
if (!n)
break;
ss(a);
vector<PII> v;
GetNext(a, n);
/*rep(i, 0, n)
printf("%d ", nxt[i]);
puts("");*/
rep(i, 2, n)
{
int ans = 1;
if (nxt[i] && !(i % (i - nxt[i])))
{
ans = i / (i - nxt[i]);
v.pb(make_pair(i, ans));
}
}
printf("Test case #%d\n", cas++);
for (auto i : v)
{
pdd(i.fi, i.se);
}
puts("");
}
return 0;
}