原题目:
Given two strings a and b we define a*b to be their concatenation. For example, if a = "abc" and b = "def" then a*b = "abcdef". If we think of concatenation as multiplication, exponentiation by a non-negative integer is defined in the normal way: a^0 = "" (the empty string) and a^(n+1) = a*(a^n).
Input
Each test case is a line of input representing s, a string of printable characters. The length of s will be at least 1 and will not exceed 1 million characters. A line containing a period follows the last test case.
Output
For each s you should print the largest n such that s = a^n for some string a.
Sample Input
abcd aaaa ababab .
Sample Output
1 4 3
Hint
This problem has huge input, use scanf instead of cin to avoid time limit exceed.
中文概要:
总结起来就是这个字符串由几个相同的小串组成。
#include <cstdio>
#include <cstring>
#include<iostream>
using namespace std;
char s[1000005];
int ne[1000001];
void GetNext(char *a)
{
int len = strlen(a);
int i = 0, j = -1;
ne[0] = -1;
while(i < len)
{
if(j == -1 || a[i] == a[j])
{
ne[++i] = ++j;
}
else j = ne[j];
}
}
int main()
{
while(scanf("%s", s) && s[0] != '.')
{
GetNext(s);
int L = strlen(s);
if(L % (L - ne[L]) == 0)///如果第i-1位为结尾的循环必定有 i % (i - Next[i]) == 0
printf("%d\n", L/(L - ne[L]));///0~i-1共有i个字符,i / (i - Next[i])就是循环次数。
else
printf("1\n");
}
return 0;
}///这道题简单在从头开始的前缀
思路:
就是一个定理。。我也不知道为啥。。不过用到了next数组的几个应用
定理:假设S的长度为len,则S存在循环子串,当且仅当,len可以被len - next[len]整除,最短循环子串为S[len - next[len]]
例子证明:
设S=q1q2q3q4q5q6q7q8,并设next[8] = 6,此时str = S[len - next[len]] = q1q2,由字符串特征向量next的定义可知,q1q2q3q4q5q6 = q3q4q5q6q7q8,即有q1q2=q3q4,q3q4=q5q6,q5q6=q7q8,即q1q2为循环子串,且易知为最短循环子串。由以上过程可知,若len可以被len - next[len]整除,则S存在循环子串,否则不存在。
解法:利用KMP算法,求字符串的特征向量next,若len可以被len - next[len]整除,则最大循环次数n为len/(len - next[len]),否则为1。