zoukankan      html  css  js  c++  java
  • HDU 3374 String 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
     
    题意:一个长度为n的字符串,通过每次循环移位可以得到n个字符串,那么现在需要输出字典序最小的那个字符串出现的位置及其出现的次数,还有字典序最大的字符串出现的最早位置及其出现的次数,新的方法(最大最小表示)。
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    
    const int N=1e6+10;
    
    char s[N*2], a[N]; ///s存放两个a字符串,供循环移位时需要
    int Next[N], la;
    
    void Getnext() ///这个Next数组存放a的Next值
    {
        int i = 0, j = -1;
    
        Next[0] = -1;
    
        while (i <= la)
        {
            if (j == -1 || a[i] == a[j])
            {
                i++;
                j++;
    
                Next[i] = j;
            }
            else j = Next[j];
        }
    }
    
    int GetMin() ///求出字典序最小的字符串最早出现的位置
    {
        int i = 0, j = 1, k; ///这里i!=j,可以将s[i+k]和s[j+k]分别看做两个字符串的首字符(相当于在判断两个字符串的大小)
    
        while (i < la && j < la)
        {
            k = 0; ///k记录字符相等的个数
    
            while (s[i+k] == s[j+k] && k < la) k++;
    
            if (k == la) break; ///若是la个字符都相等,那么可以确定两个字符串都是最小的,已经找到最小,停止查找
    
            if (s[i+k] > s[j+k]) ///因为是求最小的,所以大的那个下标要后移,而小的值不变(类似求最小值,一直更新)
            {
                if (i+k > j) i = i+k+1;
                else i = j+1;
            }
            else
            {
                if (j+k > i) j = j+k+1;
                else j = i+1;
            }
        }
    
        return min(i, j); ///因为要最早,所以求最小值
    }
    
    int GetMax() ///求出字典序最大的字符串最早出现的位置
    {
        int i = 0, j = 1, k;
    
        while (i < la && j < la)
        {
            k = 0;
    
            while (s[i+k] == s[j+k] && k < la) k++;
    
            if (k == la) break;
    
            if (s[i+k] > s[j+k]) ///那么这里就是小的值向后移,大的值不变了
            {
                if (j+k > i) j = j+k+1;
                else j = i+1;
            }
            else
            {
                if (i+k > j) i = i+k+1;
                else i = j+1;
            }
        }
    
        return min(i, j);
    }
    
    int main ()
    {
        int x, Time, Miid, Maid; ///x记录循环节的长度,Time记录出现的次数
    
        while (scanf("%s", a) != EOF)
        {
            strcpy(s, a);
            strcat(s, a);
            la = strlen(a);
    
            Getnext();
    
            x = la - Next[la];
            Time = la / x; ///可以得出最小值和最大值出现次数都为循环节的个数
    
            Miid = GetMin();
            Maid = GetMax();
    
            printf("%d %d %d %d
    ", Miid+1, Time, Maid+1, Time); ///因为下标都是从0开始的,所以要加1
        }
    
        return 0;
    }
  • 相关阅读:
    mysql 8安装
    MYSQL escape用法--转义
    为什么lombok不起作用
    zookeeper的作用
    限流的玩法汇总
    Golang程序调试工具介绍(gdb vs dlv)
    净化Git之rebase变基的使用
    深入linux下磁盘Disk,分区Partition,挂载Mount
    利用SSH(无密码)免登录来节省你的生命
    tcp_tw_reuse、tcp_tw_recycle注意事项
  • 原文地址:https://www.cnblogs.com/syhandll/p/4864589.html
Copyright © 2011-2022 走看看