zoukankan      html  css  js  c++  java
  • HDU 3374(最小最大表示法+KMP)

    传送门

    String Problem

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 4445    Accepted Submission(s): 1814

    Problem Description

    Give you a string with length N, you can generate N strings by left shifts. For example let consider the string “SKYLONG”, we can generate seven strings:
    String Rank 
    SKYLONG 1
    KYLONGS 2
    YLONGSK 3
    LONGSKY 4
    ONGSKYL 5
    NGSKYLO 6
    GSKYLON 7
    and lexicographically first of them is GSKYLON, lexicographically last is YLONGSK, both of them appear only once.
      Your task is easy, calculate the lexicographically fisrt string’s Rank (if there are multiple answers, choose the smallest one), its times, lexicographically last string’s Rank (if there are multiple answers, choose the smallest one), and its times also.

    Input

      Each line contains one line the string S with length N (N <= 1000000) formed by lower case letters.

    Output

    Output four integers separated by one space, lexicographically fisrt string’s Rank (if there are multiple answers, choose the smallest one), the string’s times in the N generated strings, lexicographically last string’s Rank (if there are multiple answers, choose the smallest one), and its times also.

    Sample Input

    abcder aaaaaa ababab

    Sample Output

    1 1 6 1 1 6 1 6 1 3 2 3

    题目描述:

        给你一个字符串,让你求出其的最小表示的首个位置以及最大表示的首个位置以及最小最大表示分别出现了多少次。

    题目分析:

        这是一个很棒的综合性字符串模板的问题。其中包括了最小表示法、最大表示法的求法以及KMP的运用。

        其中最小表示为n个循环同构字符串中,字典序最小的一个(最大表示为字典序最大的一个)。

        对于最小最大表示,我们可以通过双指针在O(n)的时间内求出。

        对于第二个要求,题目要求我们求出最小最大表示出现的次数,不难发现,他们出现的次数跟等于循环节的个数,我们可以通过KMP的next数组进行求解。时间复杂度同样是O(n)。

    代码:

    #include <bits/stdc++.h>
    #define maxn 2000005
    using namespace std;
    char str[maxn];
    int nextt[maxn];
    void get_next(char *a,int len){//求解next数组板子
        int i=0,j=nextt[0]=-1;
        while(i<len){
            while(j!=-1&&a[i]!=a[j]) j=nextt[j];
            nextt[++i]=++j;
        }
    }
    int get_minn(char *a,int len){//最小表示法板子
        int i=0,j=1;
        for(int i=0;i<len;i++){
            str[i+len]=str[i];
        }
        while(i<len&&j<len){
            int k;
            for(k=0;k<len&&a[k+i]==a[k+j];k++);
            if(k==len) break;
            if(a[k+i]>a[k+j]){
                i=i+k+1;
                if(i==j) i++;
            }
            else{
                j=j+k+1;
                if(i==j) j++;
            }
        }
        return min(i,j);
    }
    int get_maxx(char *a,int len){//最大表示法板子
        int i=0,j=1;
        for(int i=0;i<len;i++){
            str[i+len]=str[i];
        }
        while(i<len&&j<len){
            int k;
            for(k=0;k<len&&a[k+i]==a[k+j];k++);
            if(k==len) break;
            if(a[k+i]<a[k+j]){
                i=i+k+1;
                if(i==j) i++;
            }
            else{
                j=j+k+1;
                if(i==j) j++;
            }
        }
        return min(i,j);
    }
    int main()
    {
        while(~scanf("%s",str)){
            int len=strlen(str);
            memset(nextt,0,sizeof(nextt));
            get_next(str,len);
            int minn=get_minn(str,len);
            int maxx=get_maxx(str,len);
            int tmp=nextt[len];
            if(len%(len-tmp)!=0){
                cout<<minn+1<<" 1 "<<maxx+1<<" 1"<<endl;
            }
            else{
                cout<<minn+1<<" "<<len/(len-tmp)<<" "<<maxx+1<<" "<<len/(len-tmp)<<endl;
            }
        }
    }
    
  • 相关阅读:
    javascript基金会——鼠标事件,系统对话框,等等。
    面向对象的方式进行数据交换网络之间的差异
    A*寻路算法lua实现
    鸟哥Linux私房菜 基础学习篇读书笔记(10):Linux磁盘和文件系统管理(3)
    JEECG移动解决方案
    JavaScript事件收集
    OSChina 的URL类的源代码重写过程
    正则表达式注意事项
    随着通信和编程,它是一门艺术系列3(沟通的目的)
    Snmp常用oid
  • 原文地址:https://www.cnblogs.com/Chen-Jr/p/11007237.html
Copyright © 2011-2022 走看看