zoukankan      html  css  js  c++  java
  • [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
  • 相关阅读:
    对于Sobel算子的学习
    HDU 2594(求最长公共前后缀 kmp)
    HDU 6108(整除判断 数学)
    HDU 5968(异或计算 暴力)
    HDU 5963(游戏 博弈+规律)
    简单算法考题记录
    flex与bison
    C++ 智能指针
    Linux 添加设备驱动程序
    Linux 添加系统调用
  • 原文地址:https://www.cnblogs.com/hfctf0210/p/10852838.html
Copyright © 2011-2022 走看看