• BZOJ 3998 [TJOI2015]弦论 ——后缀自动机


    直接构建后缀自动机。

    然后

    然后只需要再后缀自动机的go树上类似二分的方法进行查找即可,实际上是“26分”。

    然后遇到了处理right集合的问题,然后觉得在go和parent树上上传都是可以的,毕竟一个是向后添加(go),而另一个是向前添加(parent),然后计算出来之后就类似平衡树的查找方式进行查找即可。

    然后就A掉了

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
     
    #define F(i,j,k) for (int i=j;i<=k;++i)
    #define D(i,j,k) for (int i=j;i>=k;--i)
    #define maxn 1000005
     
    struct SuffixAuto{
        char s[maxn];
        int last,cnt,t,k,len,v[maxn],q[maxn],rit[maxn];
        int l[maxn],go[maxn][26],fa[maxn],sum[maxn];
        void init()
        {
            memset(go,0,sizeof go);
            last=cnt=1;
        }
        void add(int x)
        {
            int p=last,np=last=++cnt; l[np]=l[p]+1; rit[np]=1;
            for (;p&&!go[p][x];p=fa[p]) go[p][x]=np;
            if (!p) fa[np]=1;
            else
            {
                int q=go[p][x];
                if (l[q]==l[p]+1) fa[np]=q;
                else
                {
                    int nq=++cnt;
                    l[nq]=l[p]+1;
                    memcpy(go[nq],go[q],sizeof go[q]);
                    fa[nq]=fa[q];
                    fa[q]=fa[np]=nq;
                    for (;p&&go[p][x]==q;p=fa[p]) go[p][x]=nq;
                }
            }
        }
        void build()
        {
            scanf("%s",s+1); len=strlen(s+1);
            F(i,1,len) add(s[i]-'a');
            scanf("%d%d",&t,&k);
            F(i,1,cnt) v[l[i]]++;
            F(i,1,len) v[i]+=v[i-1];
            D(i,cnt,1) q[v[l[i]]--]=i;
            D(i,cnt,1)
            {
                int tmp=q[i];
                if (t) rit[fa[tmp]]+=rit[tmp];
                else rit[tmp]=1;
            }
            rit[1]=0;
            D(i,cnt,1)
            {
                int tmp=q[i];
                sum[tmp]=rit[tmp];
                F(j,0,25) sum[tmp]+=sum[go[tmp][j]];
            }
        }
        void dfs(int o,int x)
        {
            if (x<=rit[o]) return ;
            x-=rit[o];
            F(i,0,25)
            if (go[o][i]){
                if (x>sum[go[o][i]]) x-=sum[go[o][i]];
                else
                {
                    printf("%c",'a'+i);
                    dfs(go[o][i],x);
                    return;
                }
            }
        }
        void solve()
        {
            if (k>sum[1]) printf("-1
    ");
            else dfs(1,k);
        }
    }sam;
     
    int main()
    {
        sam.init();
        sam.build();
        sam.solve();
    }
    

      

  • 相关阅读:
    表格文字溢出用省略号代替处理方法
    【Linux】Mysql5.7.12源码编译安装及配置
    【Linux】JDK安装及配置
    [SDOI2017]序列计数
    P1777 帮助_NOI导刊2010提高(03)
    BSGS和EXBSGS
    排列最小值
    三元组[01 Trie计数]
    数学题
    The Preliminary Contest for ICPC Asia Xuzhou 2019 E XKC's basketball team [单调栈上二分]
  • 原文地址:https://www.cnblogs.com/SfailSth/p/6486783.html
Copyright © 2020-2023  润新知