http://acm.fzu.edu.cn/problem.php?pid=1901
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=70325#problem/Q
Description
For each prefix with length P of a given string S,if
S[i]=S[i+P] for i in [0..SIZE(S)-p-1],
then the prefix is a “period” of S. We want to all the periodic prefixs.
Input
Input contains multiple cases.
The first line contains an integer T representing the number of cases. Then following T cases.
Each test case contains a string S (1 <= SIZE(S) <= 1000000),represents the title.S consists of lowercase ,uppercase letter.
Output
For each test case, first output one line containing "Case #x: y", where x is the case number (starting from 1) and y is the number of periodic prefixs.Then output the lengths of the periodic prefixs in ascending order.
Sample Input
4
ooo
acmacmacmacmacma
fzufzufzuf
stostootssto
Sample Output
Case #1: 3
1 2 3
Case #2:
6 3 6 9 12 15 16
Case #3: 4
3 6 9 10
Case #4: 2
9 12
给你一个字符串 s 求出所有满足s[i] == s[i+p] ( 0 < i+p < len )的 p ;
其实就是这个字符串的后缀与前缀的最大匹配 next[N],然后用最大匹配的串继续找匹配的前缀,比如下面的数据:
aaabaaa:--> P = 4 <---> next[7] = 3
aaabaaa:--> P = 5 <---> next[3] = 2
aaabaaa:--> P = 6 <---> next[2] = 1
aaabaaa:--> P = 7 <---> next[1] = 0
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> using namespace std; const int maxn = 1000050; char s[maxn]; int Next[maxn], ans[maxn]; void FindNext(char s[]) { int slen = strlen(s), i=0, j=-1; Next[0] = -1; while(i<slen) { if(j==-1 || s[i]==s[j]) Next[++i] = ++j; else j = Next[j]; } } int main() { int t, iCase=1; scanf("%d", &t); while(t--) { scanf("%s", s); int len = strlen(s); FindNext(s); int cnt = 0, k=len; while(Next[k]!=0) { ans[cnt++] = len-Next[k]; /// 第 cnt 个子串结束的下标, 表示自己觉得很神奇 k = Next[k]; } printf("Case #%d: %d\n", iCase++, cnt+1); for(int i=0; i<cnt; i++) printf("%d ", ans[i]); printf("%d\n", len); } return 0; }
勿忘初心