牛客网 牛客网暑期ACM多校训练营(第三场)E 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

题意   给定一个字符串T 设长度为n   然由这个字符串产生出n个字符串s0...sn-1  si=Ti-Tn-1+T0-Ti-1 将si相同的分到一组   i 按照从小到大排序 输出分组后的 i 序列

解析   我们可以推导一下 若T是不循环的 那么没有相同的  若是循环的 最小循环节为len 那么共有len 组   i 就属于 i%len这一组

   KMP判断是否循环 且找出最小循环节长度  随便 保存一下 也可以哈希。。。

 1 #include <bits/stdc++.h>
 2 #define pb push_back
 3 #define mp make_pair
 4 #define fi first
 5 #define se second
 6 #define all(a) (a).begin(), (a).end()
 7 #define fillchar(a, x) memset(a, x, sizeof(a))
 8 #define huan printf("\n");
 9 #define debug(a,b) cout<<a<<" "<<b<<" ";
10 using namespace std;
11 typedef long long ll;
12 const int maxn=1e6+10,inf=0x3f3f3f3f;
13 const ll mod=1e9+7;
14 char t[maxn];
15 int _next[maxn];
16 int tlen,slen;
17 void getnext()
18 {
19     int j,k;
20     j=0,k=-1,_next[0]=-1;
21     while(j<=tlen)
22         if(k==-1||t[j]==t[k])
23             _next[++j]=++k;
24         else
25             k=_next[k];
26 }
27 int main()
28 {
29     while(scanf("%s",t)!=EOF)
30     {
31         tlen=strlen(t);
32         set<int> s[tlen+10];
33         getnext();
34         if(tlen%(tlen-_next[tlen])==0)
35         {
36             int len=tlen-_next[tlen];
37             for(int i=0;i<tlen;i++)
38                 s[i%len].insert(i);
39             printf("%d\n",len);
40             for(int i=0;i<len;i++)
41             {
42                 printf("%d",s[i].size());
43                 for(auto it=s[i].begin();it!=s[i].end();it++)
44                 {
45                     printf(" %d",*it);
46                 }
47                 huan;
48              }
49         }
50         else
51         {
52             printf("%d\n",tlen);
53             for(int i=0;i<tlen;i++)
54                 printf("%d %d\n",1,i);
55         }
56     }
57 }

 

转载于:https://www.cnblogs.com/stranger-/p/9397210.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值