A:

题意:给出一个主序列,和一个匹配序列,如果能够匹配,则输出匹配序列第一个数在主序列中的位置.

思路:KMP的模版题不多说

 1 #include <stdio.h>
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <stdbool.h>
 5 #include <stdlib.h>
 6 #include <string>
 7 #include <string.h>
 8 #include <math.h>
 9 #include <vector>
10 #include <queue>
11 #include <stack>
12 #include <set>
13 #include <map>
14 
15 #define INF 0x3f3f3f3f
16 #define LL long long
17 #define MAXN 1000010
18 using namespace std;
19 
20 int len1,len2;
21 int P[MAXN],S[MAXN];
22 
23 void GetNext(int P[], int next[])
24 {
25     int p_len = len1;
26     int i = 0;
27     int j = -1;
28     next[0] = -1;
29 
30     while (i < p_len)
31     {
32         if (j == -1 || P[i] == P[j])
33         {
34             i++;
35             j++;
36             next[i] = j;
37         }
38         else
39             j = next[j];
40     }
41 }
42 
43 
44 int KMP(int S[],int P[], int next[])
45 {
46     GetNext(P, next);
47 
48     int i = 0;
49     int j = 0;
50     int s_len = len2;
51     int p_len = len1;
52 
53     while (i < s_len && j < p_len)
54     {
55         if (j == -1 || S[i] == P[j])
56         {
57             i++;
58             j++;
59         }
60         else
61             j = next[j];
62     }
63 
64     if (j == p_len)
65         return i - j + 1;
66 
67     return -1;
68 }
69 
70 int main()
71 {
72     ios_base::sync_with_stdio(0);
73     cin.tie(NULL);
74     int n;
75     cin >> n;
76     while (n--)
77     {
78         int next[1000010] = { 0 };
79         cin >> len2 >> len1;
80         for (int i=0;i<len2;i++)
81             cin >> S[i];
82         for (int i=0;i<len1;i++)
83             cin >> P[i];
84         GetNext(P,next);
85         cout << KMP(S,P,next) << endl;
86     }
87 
88     return 0;
89 }
Ackerman

 

B:

题意:计算模式串在匹配串中出现的次数

思路:直接将KMP算法稍稍改动一点就好了

 1 #include <stdio.h>
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <stdbool.h>
 5 #include <stdlib.h>
 6 #include <string>
 7 #include <string.h>
 8 #include <math.h>
 9 #include <vector>
10 #include <queue>
11 #include <stack>
12 #include <set>
13 #include <map>
14 
15 #define INF 0x3f3f3f3f
16 #define LL long long
17 #define MAXN 1000010
18 using namespace std;
19 
20 int len1,len2;
21 char P[MAXN],S[MAXN];
22 int cnt = 0;
23 
24 void GetNext(char P[], int next[])
25 {
26     int p_len = len1;
27     int i = 0;
28     int j = -1;
29     next[0] = -1;
30 
31     while (i < p_len)
32     {
33         if (j == -1 || P[i] == P[j])
34         {
35             i++;
36             j++;
37             next[i] = j;
38         }
39         else
40             j = next[j];
41     }
42 }
43 
44 
45 int KMP(char S[],char P[], int next[])
46 {
47     GetNext(P, next);
48 
49     int i = 0;
50     int j = 0;
51     int s_len = len2;
52     int p_len = len1;
53 
54     while (i < s_len)
55     {
56         if (j == -1 || S[i] == P[j])
57         {
58             i++;
59             j++;
60         }
61         else
62             j = next[j];
63         if (j == p_len)
64             cnt++;
65     }
66 
67 
68     return cnt;
69 }
70 
71 int main()
72 {
73     ios_base::sync_with_stdio(0);
74     cin.tie(NULL);
75     int n;
76     cin >> n;
77     while (n--)
78     {
79         int next[MAXN] = {0};
80         cin >> P;
81         cin >> S;
82         cnt = 0;
83         len2 = strlen(S);
84         len1 = strlen(P);
85         GetNext(P,next);
86         cout << KMP(S,P,next) << endl;
87     }
88     return 0;
89 }
Ackerman

 

C:

题意:与B一样也是计算模式串在匹配串中出现的次数

思路:代码大致和B一样。但是需要注意的是B题可以重复匹配:比如AZAZA  我们可是匹配的是AZA或者AZA

但是在C题是不可以这个样子的,所以我们稍微改动一下也可以AC

 1 #include <stdio.h>
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <stdbool.h>
 5 #include <stdlib.h>
 6 #include <string>
 7 #include <string.h>
 8 #include <math.h>
 9 #include <vector>
10 #include <queue>
11 #include <stack>
12 #include <set>
13 #include <map>
14 
15 #define INF 0x3f3f3f3f
16 #define LL long long
17 #define MAXN 1000010
18 using namespace std;
19 
20 int len1,len2;
21 char P[MAXN],S[MAXN];
22 int cnt = 0;
23 
24 void GetNext(char P[], int next[])
25 {
26     int p_len = len1;
27     int i = 0;
28     int j = -1;
29     next[0] = -1;
30 
31     while (i < p_len)
32     {
33         if (j == -1 || P[i] == P[j])
34         {
35             i++;
36             j++;
37             next[i] = j;
38         }
39         else
40             j = next[j];
41     }
42 }
43 
44 
45 int KMP(char S[],char P[], int next[])
46 {
47     GetNext(P, next);
48 
49     int i = 0;
50     int j = 0;
51     int s_len = len2;
52     int p_len = len1;
53 
54     while (i < s_len)
55     {
56         if (j == -1 || S[i] == P[j])
57         {
58             i++;
59             j++;
60         }
61         else
62             j = next[j];
63         if (j == p_len) {
64             cnt++;
65             j=0;
66         }
67     }
68 
69 
70     return cnt;
71 }
72 
73 int main()
74 {
75     ios_base::sync_with_stdio(0);
76     cin.tie(NULL);
77     while (cin >> S)
78     {
79         if (strcmp(S,"#") == 0)
80             break;
81         cin >> P;
82         int next[MAXN] = {0};
83         len1 = strlen(P);
84         len2 = strlen(S);
85         GetNext(P,next);
86         cnt = 0;
87         cout << KMP(S,P,next) << endl;
88     }
89     return 0;
90 }
Ackerman

 

D:

题意:给一串字符串,问至少添加多少个字符,使得这个字符串有至少两个循环节

思路:其实就是对kmp算法的next数组的理解;

next数组的一些应用:

1、判断是否是周期字符串:  n%(n-next[n]) == 0

2、求循环节的长度: n-next[n]

3、求循环节的个数:n/(n-next[n])

 1 #include <stdio.h>
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <stdbool.h>
 5 #include <stdlib.h>
 6 #include <string>
 7 #include <string.h>
 8 #include <math.h>
 9 #include <vector>
10 #include <queue>
11 #include <stack>
12 #include <set>
13 #include <map>
14 
15 #define INF 0x3f3f3f3f
16 #define LL long long
17 #define MAXN 1000010
18 using namespace std;
19 
20 int len1,len2;
21 char P[MAXN],S[MAXN];
22 int cnt = 0;
23 
24 void GetNext(char P[], int next[])
25 {
26     int p_len = len1;
27     int i = 0;
28     int j = -1;
29     next[0] = -1;
30 
31     while (i < p_len)
32     {
33         if (j == -1 || P[i] == P[j])
34         {
35             i++;
36             j++;
37             next[i] = j;
38         }
39         else
40             j = next[j];
41     }
42 }
43 
44 
45 int KMP(char S[],char P[], int next[])
46 {
47     GetNext(P, next);
48 
49     int i = 0;
50     int j = 0;
51     int s_len = len2;
52     int p_len = len1;
53 
54     while (i < s_len)
55     {
56         if (j == -1 || S[i] == P[j])
57         {
58             i++;
59             j++;
60         }
61         else
62             j = next[j];
63         if (j == p_len) {
64             cnt++;
65             j=0;
66         }
67     }
68 
69 
70     return cnt;
71 }
72 
73 int main()
74 {
75     ios_base::sync_with_stdio(0);
76     cin.tie(NULL);
77     int n;
78     cin >> n;
79     while (n--)
80     {
81         cin >> P;
82         int next[MAXN] = {0};
83         len1 = strlen(P);
84         GetNext(P,next);
85         int cir = len1-next[len1]; //循环节的长度
86         if (next[len1] == 0)         {
87             printf("%d\n",len1);
88             continue;
89         }
90         if (len1%cir == 0)// 判断是否是周期字符串
91         {
92             printf("0\n");
93             continue;
94         }
95         int count = len1/cir;
96         printf("%d\n",(count+1)*cir-len1);
97     }
98     return 0;
99 }
Ackerman

 

E:

题意:求出所有前缀(满足是两个或两个以上的循环节组成的字符串)

思路:只要知道next数组的应用,这题直接水过

 1 #include <stdio.h>
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <stdbool.h>
 5 #include <stdlib.h>
 6 #include <string>
 7 #include <string.h>
 8 #include <math.h>
 9 #include <vector>
10 #include <queue>
11 #include <stack>
12 #include <set>
13 #include <map>
14 
15 #define INF 0x3f3f3f3f
16 #define LL long long
17 #define MAXN 1000010
18 using namespace std;
19 
20 int len1,len2;
21 char P[MAXN],S[MAXN];
22 int cnt = 0;
23 
24 void GetNext(char P[], int next[])
25 {
26     int p_len = len1;
27     int i = 0;
28     int j = -1;
29     next[0] = -1;
30 
31     while (i < p_len)
32     {
33         if (j == -1 || P[i] == P[j])
34         {
35             i++;
36             j++;
37             next[i] = j;
38         }
39         else
40             j = next[j];
41     }
42 }
43 
44 
45 int KMP(char S[],char P[], int next[])
46 {
47     GetNext(P, next);
48 
49     int i = 0;
50     int j = 0;
51     int s_len = len2;
52     int p_len = len1;
53 
54     while (i < s_len)
55     {
56         if (j == -1 || S[i] == P[j])
57         {
58             i++;
59             j++;
60         }
61         else
62             j = next[j];
63         if (j == p_len) {
64             cnt++;
65             j=0;
66         }
67     }
68 
69 
70     return cnt;
71 }
72 
73 int main()
74 {
75     ios_base::sync_with_stdio(0);
76     cin.tie(NULL);
77     int n;
78     int t = 1;
79     while (cin >> n)
80     {
81         if (n == 0)
82             break;
83         printf("Test case #%d\n",t++);
84         cin >> P;
85         int next[MAXN] = {0};
86         len1 = n;
87         GetNext(P,next);
88         for (int i=1;i<=len1;i++) {
89             if(i%(i-next[i])==0 && (i/(i-next[i]))>1)
90                 printf("%d %d\n",i,i/(i-next[i]));
91         }
92         printf("\n");
93     }
94     return 0;
95 }
Ackerman

 

F:

题意: 求字符串的周期

水~

 1 #include <stdio.h>
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <stdbool.h>
 5 #include <stdlib.h>
 6 #include <string>
 7 #include <string.h>
 8 #include <math.h>
 9 #include <vector>
10 #include <queue>
11 #include <stack>
12 #include <set>
13 #include <map>
14 
15 #define INF 0x3f3f3f3f
16 #define LL long long
17 #define MAXN 1000020
18 using namespace std;
19 
20 int len1,len2;
21 char P[MAXN],S[MAXN];
22 int cnt = 0;
23 int nexts[MAXN];
24 
25 void GetNext(char P[], int next[])
26 {
27     int p_len = len1;
28     int i = 0;
29     int j = -1;
30     next[0] = -1;
31 
32     while (i < p_len)
33     {
34         if (j == -1 || P[i] == P[j])
35         {
36             i++;
37             j++;
38             next[i] = j;
39         }
40         else
41             j = next[j];
42     }
43 }
44 
45 
46 int KMP(char S[],char P[], int next[])
47 {
48     GetNext(P, next);
49 
50     int i = 0;
51     int j = 0;
52     int s_len = len2;
53     int p_len = len1;
54 
55     while (i < s_len)
56     {
57         if (j == -1 || S[i] == P[j])
58         {
59             i++;
60             j++;
61         }
62         else
63             j = next[j];
64         if (j == p_len) {
65             cnt++;
66             j=0;
67         }
68     }
69 
70 
71     return cnt;
72 }
73 
74 int main()
75 {
76     while (~scanf("%s",P))
77     {
78         getchar();
79         if (strcmp(P,".") == 0)
80             break;
81         len1 = strlen(P);
82         GetNext(P,nexts);
83         if (len1%(len1-nexts[len1])==0)
84             printf("%d\n",len1/(len1-nexts[len1]));
85         else
86             printf("1\n");
87     }
88     return 0;
89 }
Ackerman

 

G:

题意:给出一个字符串str,求出str中存在多少子串,使得这些子串既是str的前缀,又是str的后缀。从小到大依次输出这些子串的长度。

思路:这题挺有意思的。

next数组表示的是i前面的几个的和最前面的几个相等。那么我们不妨就从最后开始,那不就是后缀和前缀了吗?然后next不断往前移动直到0或者-1停止

 1 #include <stdio.h>
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <stdbool.h>
 5 #include <stdlib.h>
 6 #include <string>
 7 #include <string.h>
 8 #include <math.h>
 9 #include <vector>
10 #include <queue>
11 #include <stack>
12 #include <set>
13 #include <map>
14 
15 #define INF 0x3f3f3f3f
16 #define LL long long
17 #define MAXN 1000020
18 using namespace std;
19 
20 int len1,len2;
21 char P[MAXN],S[MAXN];
22 int cnt = 0;
23 int nexts[MAXN];
24 int ans[MAXN];
25 
26 void GetNext(char P[], int next[])
27 {
28     int p_len = len1;
29     int i = 0;
30     int j = -1;
31     next[0] = -1;
32 
33     while (i < p_len)
34     {
35         if (j == -1 || P[i] == P[j])
36         {
37             i++;
38             j++;
39             next[i] = j;
40         }
41         else
42             j = next[j];
43     }
44 }
45 
46 
47 int KMP(char S[],char P[], int next[])
48 {
49     GetNext(P, next);
50 
51     int i = 0;
52     int j = 0;
53     int s_len = len2;
54     int p_len = len1;
55 
56     while (i < s_len)
57     {
58         if (j == -1 || S[i] == P[j])
59         {
60             i++;
61             j++;
62         }
63         else
64             j = next[j];
65         if (j == p_len) {
66             cnt++;
67             j=0;
68         }
69     }
70 
71 
72     return cnt;
73 }
74 
75 int main()
76 {
77     while (~scanf("%s",P))
78     {
79         getchar();
80         len1 = strlen(P);
81         int len = len1;
82         GetNext(P,nexts);
83         int cnt=0;
84         while (nexts[len1])
85         {
86             ans[cnt++] = nexts[len1];
87             len1 = nexts[len1];
88         }
89         sort(ans,ans+cnt);
90         for (int i=0;i<cnt;i++)
91             printf("%d ",ans[i]);
92         printf("%d\n",len);
93     }
94     return 0;
95 }
Ackerman

 

I:

题意:找前一个字符串的前缀和后一个字符串的后缀一样的最长长度

思路:把这两个字符串连起来,然后你就会发现这题其实和G题有点像。也就是看后面和最前面相等的个数最多罢了。只不过要注意虽然连起来了,但是它其实还是两个不一样的,所以如果这个相等长度比它们其中任何一个长度要大的话其实是不可以的,那就再继续找小一点的呗

  1 #include <stdio.h>
  2 #include <algorithm>
  3 #include <iostream>
  4 #include <stdbool.h>
  5 #include <stdlib.h>
  6 #include <string>
  7 #include <string.h>
  8 #include <math.h>
  9 #include <vector>
 10 #include <queue>
 11 #include <stack>
 12 #include <set>
 13 #include <map>
 14 
 15 #define INF 0x3f3f3f3f
 16 #define LL long long
 17 #define MAXN 1000020
 18 using namespace std;
 19 
 20 int len1,len2;
 21 char P[MAXN],S[MAXN];
 22 char str[MAXN];
 23 int cnt = 0;
 24 int nexts[MAXN];
 25 
 26 
 27 void GetNext(char P[], int next[])
 28 {
 29     int p_len = len1;
 30     int i = 0;
 31     int j = -1;
 32     next[0] = -1;
 33 
 34     while (i < p_len)
 35     {
 36         if (j == -1 || P[i] == P[j])
 37         {
 38             i++;
 39             j++;
 40             next[i] = j;
 41         }
 42         else
 43             j = next[j];
 44     }
 45 }
 46 
 47 
 48 int KMP(char S[],char P[], int next[])
 49 {
 50     GetNext(P, next);
 51 
 52     int i = 0;
 53     int j = 0;
 54     int s_len = len2;
 55     int p_len = len1;
 56 
 57     while (i < s_len)
 58     {
 59         if (j == -1 || S[i] == P[j])
 60         {
 61             i++;
 62             j++;
 63         }
 64         else
 65             j = next[j];
 66         if (j == p_len) {
 67             cnt++;
 68             j=0;
 69         }
 70     }
 71 
 72 
 73     return cnt;
 74 }
 75 
 76 int main()
 77 {
 78     while (~scanf("%s%s", P,S))
 79     {
 80         len2 = strlen(S);
 81         int len = strlen(P);
 82         strcat(P, S);
 83         len1 = strlen(P);
 84         GetNext(P,nexts);
 85         int ans = nexts[len1];
 86         while (ans > len || ans > len2)
 87         {
 88             ans = nexts[ans];
 89         }
 90         if (ans == 0 || ans == -1)
 91         {
 92             printf("0\n");
 93         }
 94         else
 95         {
 96             P[ans] = '\0';
 97             printf("%s %d\n",P,ans);
 98         }
 99     }
100 
101     return 0;
102 }
Ackerman

 

J:

题意:给一串字符串,问这串字符串所有的前缀总共在这个字符串中出现了几次。 

思路:其实这道题也是next数组的运用。前面已经说了next数组表示的是i之前的几个和字符串最前面的几个相等。将字符串所有的前缀0-i在i+1-n出现的次数相加得到 sum, sum再加上n就是了

 1 #include <stdio.h>
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <stdbool.h>
 5 #include <stdlib.h>
 6 #include <string>
 7 #include <string.h>
 8 #include <math.h>
 9 #include <vector>
10 #include <queue>
11 #include <stack>
12 #include <set>
13 #include <map>
14 
15 #define INF 0x3f3f3f3f
16 #define LL long long
17 #define MAXN 1000020
18 using namespace std;
19 
20 int len1,len2;
21 char P[MAXN],S[MAXN];
22 int cnt = 0;
23 int nexts[MAXN];
24 int ans[MAXN];
25 
26 
27 void GetNext(char P[], int next[])
28 {
29     int p_len = len1;
30     int i = 0;
31     int j = -1;
32     next[0] = -1;
33 
34     while (i < p_len)
35     {
36         if (j == -1 || P[i] == P[j])
37         {
38             i++;
39             j++;
40             next[i] = j;
41         }
42         else
43             j = next[j];
44     }
45 }
46 
47 
48 int KMP(char S[],char P[], int next[])
49 {
50     GetNext(P, next);
51 
52     int i = 0;
53     int j = 0;
54     int s_len = len2;
55     int p_len = len1;
56 
57     while (i < s_len)
58     {
59         if (j == -1 || S[i] == P[j])
60         {
61             i++;
62             j++;
63         }
64         else
65             j = next[j];
66         if (j == p_len) {
67             cnt++;
68             j=0;
69         }
70     }
71 
72 
73     return cnt;
74 }
75 
76 int main()
77 {
78     int T;
79     scanf("%d",&T);
80     while (T--)
81     {
82         memset(ans,0, sizeof(ans));
83         int n;
84         scanf("%d",&n);
85         scanf("%s",&P);
86         getchar();
87         len1 = strlen(P);
88         GetNext(P,nexts);
89         int sum = 0;
90         for (int i=1;i<=len1;i++)
91         {
92             ans[i] = ans[nexts[i]]+1;
93             sum += ans[i];
94         }
95         printf("%d\n",sum%10007);
96     }
97     return 0;
98 }
Ackerman

 

O:

题意:给出一段文本,求出里面"Doge"的个数,大小写不敏感.

思路:把文本合并成一段,然后之间KMP就好了

 1 #include <stdio.h>
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <stdbool.h>
 5 #include <stdlib.h>
 6 #include <string>
 7 #include <string.h>
 8 #include <math.h>
 9 #include <vector>
10 #include <queue>
11 #include <stack>
12 #include <set>
13 #include <map>
14 
15 #define INF 0x3f3f3f3f
16 #define LL long long
17 #define MAXN 200005
18 using namespace std;
19 
20 char P[MAXN];
21 char str[MAXN];
22 char S[MAXN];
23 int nexts[MAXN];
24 int cnt = 0;
25 int len1,len2;
26 
27 void GetNext(char P[], int next[])
28 {
29     int p_len = len1;
30     int i = 0;
31     int j = -1;
32     next[0] = -1;
33 
34     while (i < p_len)
35     {
36         if (j == -1 || P[i] == P[j])
37         {
38             i++;
39             j++;
40             next[i] = j;
41         }
42         else
43             j = next[j];
44     }
45 }
46 
47 
48 void KMP(char S[], char P[], int next[])
49 {
50     int i = 0;
51     int j = 0;
52     int s_len = len2;
53     int p_len = len1;
54 
55     while (i < s_len)
56     {
57         if (j == -1 || S[i] == P[j])
58         {
59             i++;
60             j++;
61         }
62         else
63             j = next[j];
64         if (j == p_len){
65             cnt++;
66         }
67     }
68 }
69 
70 int main()
71 {
72     //freopen("../in.txt","r",stdin);
73     ios_base::sync_with_stdio(0);
74     cin.tie(NULL);
75     cin >> S;
76     cnt = 0;
77     while (cin >> str)
78     {
79         strcat(S,str);
80     }
81     len2 = strlen(S);
82     for (int i=0;i<len2;i++)
83     {
84         if (S[i]>='A' && S[i]<='Z')
85         {
86             S[i]+=32;
87         }
88     }
89     P[0]='d';
90     P[1]='o';
91     P[2]='g';
92     P[3]='e';
93     P[4]='\0';
94     len1 = strlen(P);
95     GetNext(P,nexts);
96     KMP(S,P,nexts);
97     cout << cnt << endl;
98     return 0;
99 }
Ackerman

 

P:

题目意思是一个字符串中前缀后缀相等且能在中间找到,重要的一个点是三者不能重叠 EAEBE 满足这种形式

思路:先用KMP将其分为两段,然后取去掉首位,看中间的那一段是否符合就好了

  1 #include <stdio.h>
  2 #include <algorithm>
  3 #include <iostream>
  4 #include <stdbool.h>
  5 #include <stdlib.h>
  6 #include <string>
  7 #include <string.h>
  8 #include <math.h>
  9 #include <vector>
 10 #include <queue>
 11 #include <stack>
 12 #include <set>
 13 #include <map>
 14 
 15 #define INF 0x3f3f3f3f
 16 #define LL long long
 17 #define MAXN 1000020
 18 using namespace std;
 19 
 20 int len1,len2;
 21 char P[MAXN],S[MAXN];
 22 int cnt = 0;
 23 int nexts[MAXN];
 24 char str[MAXN];
 25 
 26 
 27 void GetNext(char P[], int next[])
 28 {
 29     int p_len = len1;
 30     int i = 0;
 31     int j = -1;
 32     next[0] = -1;
 33 
 34     while (i < p_len)
 35     {
 36         if (j == -1 || P[i] == P[j])
 37         {
 38             i++;
 39             j++;
 40             next[i] = j;
 41         }
 42         else
 43             j = next[j];
 44     }
 45 }
 46 
 47 
 48 int KMP(char S[],char P[], int next[])
 49 {
 50     GetNext(P, next);
 51 
 52     int i = 0;
 53     int j = 0;
 54     int s_len = len2;
 55     int p_len = len1;
 56 
 57     while (i < s_len)
 58     {
 59         if (j == -1 || S[i] == P[j])
 60         {
 61             i++;
 62             j++;
 63         }
 64         else
 65             j = next[j];
 66         if (j == p_len) {
 67             cnt++;
 68             j=0;
 69         }
 70     }
 71 
 72 
 73     return cnt;
 74 }
 75 
 76 void solve()
 77 {
 78     len1 = strlen(P);
 79     GetNext(P,nexts);
 80     int len = len1;
 81     int max_d = nexts[len1];
 82     while (2*max_d>len)
 83     {
 84         len1 = nexts[len1];
 85         max_d = nexts[len1];
 86     }
 87     int ans = 0;
 88     int flag = 1;
 89     while (max_d)
 90     {
 91         strncpy(S,P+max_d,len-2*max_d);
 92         strncpy(str,P,max_d);
 93         str[max_d] = '\0';
 94         if (S!=NULL)
 95         {
 96             flag = 0;
 97             if (ans<max_d)
 98                 ans = max_d;
 99         }
100         len1 = nexts[len1];
101         max_d = nexts[len1];
102     }
103     if (flag)
104         printf("0\n");
105     else
106         printf("%d\n",ans);
107 }
108 
109 
110 
111 int main()
112 {
113     int T;
114     scanf("%d",&T);
115     while (T--)
116     {
117         scanf("%s",P);
118         solve();
119     }
120     return 0;
121 }
Ackerman

 

 

 

训练总结:

其实感觉KMP的运用的灵活很大一部取决于next数组的运用:

next数组的一些应用:

1、判断是否是周期字符串:  n%(n-next[n]) == 0

2、求循环节的长度: n-next[n]

3、求循环节的个数:n/(n-next[n])