数据结构 02KMP
KMP模板:
求next数组
//求next数组 for (int i = 2, j = 0; i <= n; i ++ ) { while (j && p[j] != p[j + 1]) j = ne[j]; if (p[i] == p[j + 1]) j ++; ne[i] = j; }
处理母串
for (int i = 1, j = 0; i <= m; i ++ ) { while (j && s[i] != p[j + 1]) j = ne[j]; if (s[i] == s[j + 1]) j ++; if (j == n) { } f[i] == j; // if (f[i] == n)此时p在s串中第一次出现 }
假设S长度位len,则s存在最小循环节,循环节的长度L为len-ne[len], 子串为s[1, len - ne[n]]
(1)如果len可以被len-ne[len]整除,则表明字符串s完全由循环节循环组成,循环周期为T = len / L
其中L = len - ne[len]
Description 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. Source
代码:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int N = 1000010; int len; char s[N]; int ne[N]; void work() { len = strlen(s + 1); for (int i = 2, j = 0; i <= len; i ++ ) { while (j && s[i] != s[j + 1]) j = ne[j]; if (s[i] == s[j + 1]) j ++; ne[i] = j; } int t = len - ne[len]; if (len % t == 0) printf("%d\n", len / t); else puts("1"); } int main() { while (scanf("%s", s + 1)) { if (s[1] == '.') return 0; memset(ne, 0, sizeof ne); work(); } }