• [JSOI2019]节日庆典(Z-algorithm)


    要想让一个位置作为最小循环,其必须是最小后缀,然后一个字符串的最小后缀不超过O(logn)个,于是维护备选集合即可。

    然而要在O(n)复杂度求解,需要求出原串后缀与原串的LCP长度,需要用Z-algorithm。而此时由于备选后缀存在前缀关系,比较时只需用到每个后缀与原串的LCP

    #include<bits/stdc++.h>
    using namespace std;
    const int N=3e6+7;
    int n,ans,lcp[N];
    char str[N];
    vector<int>f,g;
    int cmp(int x,int len)
    {
        if(lcp[x]>=len)return 0;
        return str[1+lcp[x]]<str[x+lcp[x]]?1:-1;
    }
    int main()
    {
        scanf("%s",str+1),n=strlen(str+1);
        for(int i=2,l=1,r=1;i<=n;i++)
        {
            lcp[i]=r>=i?min(lcp[i-l+1],r-i+1):0;
            while(str[i+lcp[i]]==str[1+lcp[i]])lcp[i]++;
            if(i+lcp[i]-1>r)r=i+lcp[i]-1,l=i;
        }
        for(int i=1;i<=n;i++)
        {
            g.clear(),f.push_back(i);
            for(int j=0;j<f.size();j++)
            {
                while(g.size()&&str[i]<str[g.back()+i-f[j]])g.pop_back();
                if(!g.size()||str[i]==str[g.back()+i-f[j]]&&i-g.back()+1>=2*(i-f[j]+1))
                g.push_back(f[j]);
            }
            f=g;
            ans=f[0];
            for(int j=0;j<f.size();j++)
            {
                int y=f[j],t=cmp(ans+i-y+1,y-ans);
                if(t==1)ans=y;
                else if(!t&&cmp(y-ans+1,ans-1)==-1)ans=y;
            }
            printf("%d ",ans);
        }
    }
    View Code
  • 相关阅读:
    Python 之 面向对象(一)
    Python 之 基础知识(五)
    javaweb 之 代理模式
    Python 之 基础知识(四)
    Python 之 基础知识(三)
    如何在非 sudo 用户下运行 docker 命令?
    Leetcode 55
    Leetcode 11
    Leetcode 466
    几个内存操作函数使用
  • 原文地址:https://www.cnblogs.com/hfctf0210/p/10852838.html
Copyright © 2020-2023  润新知