FZU1901 Period II —— KMP next数组

题目链接:https://vjudge.net/problem/FZU-1901

 Problem 1901 Period II

Accept: 575    Submit: 1495
Time Limit: 1000 mSec    Memory Limit : 32768 KB

 Problem 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

 Source

FOJ有奖月赛-2010年05月

题解:

求出该字符串的所有循环节。

求出字符串的next数组。可知len-next[len]就是字符串的最小循环节,然后next数组回退,len-next[next[len]]就是第二小循环节……

代码如下:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <string>
 6 #include <vector>
 7 #include <map>
 8 #include <set>
 9 #include <queue>
10 #include <sstream>
11 #include <algorithm>
12 using namespace std;
13 typedef long long LL;
14 const double eps = 1e-6;
15 const int INF = 2e9;
16 const LL LNF = 9e18;
17 const int MOD = 1e9+7;
18 const int MAXN = 1e6+10;
19 
20 char x[MAXN];
21 int Next[MAXN];
22 
23 void get_next(char x[], int m)
24 {
25     int i, j;
26     j = Next[0] = -1;
27     i = 0;
28     while(i<m)
29     {
30         while(j!=-1 && x[i]!=x[j]) j = Next[j];
31         Next[++i] = ++j;
32     }
33 }
34 
35 int ans[MAXN];
36 int main()
37 {
38     int T, kase = 0;
39     scanf("%d", &T);
40     while(T--)
41     {
42         scanf("%s", x);
43         int len = strlen(x);
44         get_next(x, len);
45 
46         int cnt = 0;
47         for(int k = Next[len]; k!=-1; k = Next[k])
48             ans[++cnt] = len-k;
49 
50         printf("Case #%d: %d
", ++kase, cnt);
51         for(int i = 1; i<=cnt; i++)
52         {
53             printf("%d", ans[i]);
54             if(i!=cnt) printf(" ");
55         }
56         printf("
");
57     }
58 }
View Code
原文地址:https://www.cnblogs.com/DOLFAMINGO/p/7891870.html