zoukankan      html  css  js  c++  java
  • [洛谷P1709] [USACO5.5]隐藏口令Hidden Password

    洛谷题目链接:[USACO5.5]隐藏口令Hidden Password

    题目描述

    有时候程序员有很奇怪的方法来隐藏他们的口令。Binny会选择一个字符串S(由N个小写字母组成,5<=N<=5,000,000),然后他把S顺时针绕成一个圈,每次取一个做开头字母并顺时针依次取字母而组成一个字符串。这样将得到一些字符串,他把它们排序后取出第一个字符串。把这个字符串的第一个字母在原字符串中的位置-1做为口令。

    如字符串alabala,按操作的到7个字符串,排序后得:

    aalabal

    abalaal

    alaalab

    alabala

    balaala

    laalaba

    labalaa

    第一个字符串为aalabal,这个a在原字符串位置为7,7-1=6,则6为口令。

    输入输出格式

    输入格式:

    第一行:一个数:N

    第二行开始:字符串:S(每72个字符一个换行符)

    输出格式:

    一行,为得到的口令

    输入输出样例

    输入样例#1:

    7
    anabana

    输出样例#1:

    6

    说明

    题目满足:

    30%的数据n<=10000

    70%的数据n<=100000

    100%的数据n<=5000000

    时限 1s

    题目翻译来自NOCOW。

    USACO Training Section 5.5

    题解: 其实在(USACO)上的数据范围只有这里的(70\%),也就是一道后缀数组的裸题,不懂的可以戳这里.

    然而这里的数据范围扩大到了(5*10^6),(nlogn)的倍增求后缀数组是过不去的,(O(n))(DC3)好像常数非常大?反正我也不会.

    于是这里介绍一种(O(n))求循环表示下的字典序最小的字符串表示法:最小表示法.

    先介绍一下算法的过程吧:首先用两个指针(i,j)表示正在比较的两个字符串开头的位置,(k)表示已经比较过的长度,(s)表示原字符串,那么显然在比较的时候会出现这样几种情况:

    1. (s[i+k]==s[j+k]),此时直接(k++).
    2. (s[i+k]<s[j+k]),此时显然从(j)开始的字符串是不可能成为该字符串的最小表示的,此时我们让(j += k+1).
    3. (s[i+k]>s[j+k]),同上,(i += k+1).

    那么我们为什么可以直接让(j=j+k+1)呢?这是因为如果从(j)开始的字符串无法成为最小表示的话,它后面的(k)个字符都无法成为最小表示的开头.具体这个是为什么我也不会证明,可以看一下这篇博客的证明:https://blog.csdn.net/zy691357966/article/details/39854359.
    虽然我感觉这位博主用[显然]将需要证明的东西一笔带过了

    我们还需要考虑一种情况:如果(i)(j)在增加之后等于另一个怎么办?如果出现这样的情况直接让(j++)就可以了.

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 5e6+5;
    const int inf = 0x3f3f3f3f;
    
    int n;
    char s[N], tmp[80];
    
    int solve(){
        int i = 0, j = 1, k = 0;
        while(i < n && j < n && k < n){
            k = 0;
            while(k < n && s[(i+k)%n] == s[(j+k)%n]) k++;
            if(k == n) return min(i, j);
            if(s[(i+k)%n] < s[(j+k)%n]) j += k+1;
            else i += k+1;
            j += (i == j);
        }
        return min(i, j);
    }
    
    int main(){
        cin >> n;
        for(int i = 0; i < n; i++) cin >> s[i];
        printf("%d
    ", solve());
        return 0;
    }
    
  • 相关阅读:
    python抓取网站的图片并下载到本地
    常用的python模块及安装方法
    Linux查看进程和终止进程的技巧
    Linux中source命令的用法
    Pyhone 验证码那些事之安装pytesseract
    python Queue模块
    vi/vim多行注释和取消注释
    IdentityServer4第二次介入了解(1)
    一、JS前端排查小技巧
    IIS部署Core3.1
  • 原文地址:https://www.cnblogs.com/BCOI/p/10421603.html
Copyright © 2011-2022 走看看