KMP循环节

链接:https://www.nowcoder.com/acm/contest/141/E

题目描述

Eddy likes to play with string which is a sequence of characters. One day, Eddy has played with a string S for a long time and wonders how could make it more enjoyable. Eddy comes up with following procedure:

1. For each i in [0,|S|-1], let S i be the substring of S starting from i-th character to the end followed by the substring of first i characters of S. Index of string starts from 0.
2. Group up all the S i. S i and S j will be the same group if and only if S i=S j.
3. For each group, let L j be the list of index i in non-decreasing order of S i in this group.
4. Sort all the L j by lexicographical order.

Eddy can't find any efficient way to compute the final result. As one of his best friend, you come to help him compute the answer!

输入描述:

Input contains only one line consisting of a string S.

1≤ |S|≤ 10
6

S only contains lowercase English letters(i.e.
).

输出描述:

First, output one line containing an integer K indicating the number of lists.
For each following K lines, output each list in lexicographical order.
For each list, output its length followed by the indexes in it separated by a single space.
示例1

输入

复制
abab

输出

复制
2
2 0 2
2 1 3
示例2

输入

复制
deadbeef

输出

复制
8
1 0
1 1
1 2
1 3
1 4
1 5
1 6
1 7


题意:

这个题意挺不好理解,看来很久(大概是我太菜了)大概是说给你一个串,然后从第一个字母开始向末尾添加,形成一个新串,如果这个新串和以前的旧串有相同,则分为一组,编号就是这个串是第几次首字母向末尾添加,如原串就应当是0。

题解:

kMP找出循环节,当我们找到循环节时,就可以确定在第几次添加时,是一个出现过的串。

举个例子;串 abbabb

     0:  abbabb

     1:  bbabba

     2:  babbab

     3:  abbabb

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int MAXN=1e6+10;
 4 char str[MAXN];
 5 int NEXT[MAXN];
 6 int getNEXT(int l)
 7 {
 8     NEXT[0]=-1;
 9     int k=-1;
10     int j=0;
11     while (j<l)
12     {
13         if(k==-1||str[j]==str[k])
14         {
15             ++k;
16             ++j;
17             NEXT[j]=k;
18         } else{
19             k=NEXT[k];
20         }
21     }
22 }
23 int main()
24 {
25     scanf("%s",str);
26     int len=strlen(str);
27     getNEXT(len);
28     int l=len-NEXT[len];//循环节的长度;
29     if(len%l!=0)
30     {
31         printf("%d\n",len);
32         for (int i = 0; i <len ; ++i) {
33             printf("%d %d\n",1,i);
34         }
35 
36     } else
37     {
38         printf("%d\n",l);
39         for (int i = 0; i <l ; ++i) {
40             printf("%d",len/l);
41             for (int j = i; j <len ; j+=l) {
42                 printf(" %d",j);
43             }
44             printf("\n");
45         }
46     }
47 
48 
49 
50     return 0;
51 }
扫描二维码关注公众号,回复: 2410142 查看本文章

猜你喜欢

转载自www.cnblogs.com/-xiangyang/p/9377577.html