牛客多校(第三场)E Sort String

链接:https://www.nowcoder.com/acm/contest/141/E
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
Special Judge, 64bit IO Format: %lld

题目描述

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 Si 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 Si. Si and Sj will be the same group if and only if Si=Sj.
3. For each group, let Lj be the list of index i in non-decreasing order of Si in this group.
4. Sort all the Lj 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|≤ 106
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

题目大意是说给你一个字符串,可以看成一个字符串的环,从每一个位置开始,生成了n个可能相同可能不同的字符串(n为字符串的长度),求生成的字符串中有多少种不同的字符串,每种字符串的第一个字符在原字符串里的位置分别是多少。

作为一个名副其实的蒟蒻,不会哈希,kmp也是一知半解,只会用暴力。首先分析,设一个字符串为str,长度是l,那么如果会出现重复的字符串,那么原字符串一定是由任意个str组成的,那也就是说n一定是l的倍数,即l是n的因子。因为n的范围是不超过1e6的,本地跑了一下,发现他的因子不会很大,大约在五十左右。所以暴力枚举l,(n % l == 0),每一次暴力跑一遍看是不是子串。如果有子串,则会出现l种字符串,每次出现相同的字符串的间距均为l / tmp;如果没有子串,则所有字符串均不相同。

 

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
char str[1000005];
int main()
{
//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
//    std::ios::sync_with_stdio(false);
//    std::cin.tie();
//    std::cout.tie();
    int n,flag,l;
    scanf("%s", str);
    n = strlen(str);
    int tmpp = n / 2;
    for (l = 1; l <= tmpp; l++)  //枚举l
    {
        if (n % l != 0)
            continue;
        flag = 0;
        int tmp = n / l;    //str子串出现的次数
        for (int j = 0; j < l; j++) // 判断str是不是原字符串的子串
        {
            char c = str[j];
            for (int k = 1; k < tmp; k++)
                if (str[l * k + j] != c)
                {
                    flag = 1;
                    break;
                }
            if (flag)
                break;
        }
        if (!flag)
            break;
    }
    if (flag) // 如果没有子串
    {
        printf("%d\n", n);
        for (int i = 0; i < n; i++)
            printf("1 %d\n", i);
    }
    else    // 有子串
    {
        int cnt = n / l;
        printf("%d\n", l);
        for (int i = 0; i < l; i++)
        {
            printf("%d", cnt);
            int tmp = i;
            for (int j = 0; j < cnt; j++)
            {
                printf(" %d", tmp);
                tmp += l;
            }
            printf("\n");
        }
    }
    return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值