• 最小表示法


    简介

    请求解:给出一个字符串,求与它循环同构的串中字典序最小的串。
    考虑暴力,可能导致(O(n^2))(比如aaa...aaab)。
    最小表示法可以(O(n))解决:枚举两个起点,如果这两个起点i,j开始的串在匹配到第k个时不同(假设s[i + k - 1] < s[j + k - 1]),由于s[i + k - 2]对应s[j + k - 2]相等,那么对于任意串Sj+k,(k在[0,k - 1]内)总有Si+k更优。所以可以直接跳过。

    #include<iostream>
    #include<cstdio>
    using namespace std;
    inline void read(int &x)
    {
        x=0;int f=1;char c=getchar();
        for(;c<'0'||c>'9';c=getchar()) if(c=='-') f=-1;
        for(;c>='0'&&c<='9';c=getchar()) x=(x<<1)+(x<<3)+(c^48);
        x*=f;
    }
    inline void print(int x)
    {
        if(x<0){x=-x;putchar('-');};
        if(x>9) print(x/10);
        putchar(x%10+'0');
    }
    inline int cread(char a[])
    {
        int tot=0;
        char c=getchar();
        for(;c>='a'&&c<='z';c=getchar()) 
        {
            a[tot]=c;tot++;
        }
        return tot;
    }//经多次试验发现此输入常出现玄学bug,请无视此函数
    char s[10010];
    int len=0;
    int zxbsf()
    {
        int i=0,j=1,k=0,t;//取s开头两位置i,j;k为能重合的最大长度; 
        while(i<len&&j<len&&k<len)
        {
            t=s[(i+k)%len]-s[(j+k)%len];
            if(!t) k++;//i,j 上字符相同 
            else
            {
                if(t>0) i=i+k+1; 
                else j=j+k+1;//哪处字典序大哪处就跳 
                if(i==j) j++;//重合要错位处理 
                k=0;//长度置零 
            }
        }
        if(i>j) return j;
        else return i;
    }
    int main()
    {
        int gg;
        read(gg);
        while(gg--)
        {
            len=cread(s);
            print(zxbsf()+1);
            putchar('
    ');
        }
    
    } 
    

    推荐oi wiki-最小表示法

  • 相关阅读:
    关于http协议详解
    python记录_day15 面向对象初识
    python记录_day14 内置函数二 迭代 二分法
    python记录_day13 内置函数
    python记录_day12 生成器
    python记录_day11 闭包 迭代器
    函数默认参数的初始化问题
    python记录_day10 动态传参 命名空间 作用域
    python记录_day09 初识函数
    python记录_day08
  • 原文地址:https://www.cnblogs.com/Thomastine/p/11861732.html
Copyright © 2020-2023  润新知