zoukankan      html  css  js  c++  java
  • 2018牛客暑假多校三 E(KMP运用)

    题目描述:

        给你一个字符串S,你要对字符串S的每一位i将前i位的字符串移动到尾部形成一个新的字符串,如果形成的字符串相同则归为一类Li。现在让你将Li类按照字典序排序,并让你输出每一类的数量和每一类中字符串对应的下标i。

    题目分析:

        观察可以发现,将字符串移动形成新的字符串,当且仅当字符串中存在循环节时,才会出现新构成的字符串相同。因此这个问题就转化成求一个字符串的循环节的问题。

        至此,这个问题就可以用kmp中的next数组进行计算。(有一个重要结论,如果对于一个长度为L的字符串,如果L%(L-next[L])==0则代表它具有循环节,且循环节的长度为L-next[L])

    代码:

    #include <bits/stdc++.h>
    #define maxn 1000005
    using namespace std;
    int nex[maxn];
    char str[maxn];
    void get_next(char *s){//获取next数组
        int i,j;
        j=nex[0]=-1;
        i=0;
        int len=strlen(s);
        while(i<len){
            while(j!=-1&&s[i]!=s[j]) j=nex[j];
            nex[++i]=++j;
        }
    }
    int main()
    {
        scanf("%s",str);
        get_next(str);
        int len=strlen(str);
        int tmp=len-nex[len];
        if(len%tmp!=0){//如果没有循环节,则每个都类都为1
            cout<<len<<endl;
            for(int i=0;i<len;i++){
                printf("1 %d
    ",i);
            }
        }
        else{
            cout<<tmp<<endl;//字符串的种类的数目为循环节的长度
            for(int i=0;i<tmp;i++){
                cout<<len/tmp;//每个字符串种类的个数
                for(int j=i;j<len;j+=tmp){
                    cout<<" "<<j;
                }
                puts("");
            }
        }
        return 0;
    }
    
  • 相关阅读:
    LeetCode 334 Increasing Triplet
    LeetCode 笔记27 Two Sum III
    LeetCode 笔记28 Maximum Gap
    最小的图灵完备语言——BrainFuck
    蛋疼的SVG外部引用方式
    HackerRank# Hexagonal Grid
    HackerRank# The Longest Common Subsequence
    HackerRank# Bricks Game
    HackerRank# Fibonacci Modified
    HackerRank# Knapsack
  • 原文地址:https://www.cnblogs.com/Chen-Jr/p/11007256.html
Copyright © 2011-2022 走看看