zoukankan      html  css  js  c++  java
  • [bzoj3998][TJOI2015]弦论_后缀自动机

    弦论 bzoj-3998 TJOI-2015

    题目大意:给定一个字符串,求其$k$小子串。

    注释:$1le length le 5cdot 10^5$,$1le kle 10^9$。


    想法

    后缀数组傻逼题。

    初学后缀自动机我们尝试用后缀自动机解决。

    首先先建出$SAM$。

    分别考虑$T=0$和$T=1$的情况。

    我们处理$f$数组表示以当前节点代表的字符串为前缀的子串个数。

    它们俩之间的区别就是$Right$集合的大小。

    详情看代码把。

    代码

    #include <bits/stdc++.h>
    #define N 1000010 
    using namespace std;
    int n,opt,nxt[N][26],fa[N],dis[N],lst=1,cnt=1,v[N],q[N],Right[N],f[N];
    char str[N];
    void update(int c)
    {
        int p=lst,np=lst=++cnt;
        dis[np]=dis[p]+1; Right[np]=1;
        while(p&&!nxt[p][c]) nxt[p][c]=np,p=fa[p];
        if(!p) fa[np]=1;
        else
        {
            int q=nxt[p][c];
            if(dis[q]==dis[p]+1) fa[np]=q;
            else
            {
                int nq=++cnt;
                memcpy(nxt[nq],nxt[q],sizeof nxt[q]);
                dis[nq]=dis[p]+1; fa[nq]=fa[q]; fa[np]=fa[q]=nq;
                while(p&&nxt[p][c]==q) nxt[p][c]=nq,p=fa[p];
            }
        }
    }
    void init()
    {
        for(int i=1;i<=cnt;i++) v[dis[i]]++;
        for(int i=1;i<=n;i++) v[i]+=v[i-1];
        for(int i=cnt;i;i--) q[v[dis[i]]--]=i;
        for(int i=cnt;i;i--)
        {
            int t=q[i];
            if(opt) Right[fa[t]]+=Right[t];
            else Right[t]=1;
        }
        Right[1]=0; for(int i=cnt;i;i--)
        {
            int t=q[i]; f[t]=Right[t];
            for(int j=0;j<26;j++) f[t]+=f[nxt[t][j]];
        }
    }
    void query(int p,int k)
    {
        if(k<=Right[p]) return;
        k-=Right[p];
        for(int i=0;i<26;i++) if(nxt[p][i])
        {
            if(k<=f[nxt[p][i]])
            {
                putchar(i+'a'); query(nxt[p][i],k);
                return;
            }
            k-=f[nxt[p][i]];
        }
    }
    int main()
    {
        int k; scanf("%s%d%d",str+1,&opt,&k); n=strlen(str+1);
        for(int i=1;i<=n;i++) update(str[i]-'a');
        init();
        if(k>f[1]) puts("-1");
        else query(1,k);
        return 0;
    }
    

    小结:后缀自动机搭配其他的数据结构的时候会比较有用,但是感觉后缀数组更好写啊$qwq$......

  • 相关阅读:
    Flexera Software发布支持Visual Studio 2010的扩展包
    InstallShield 2010 SP1发布
    InstallShield 2010 Limited Edition试用
    InstallAnywhere 2009发布SP2
    INFO:Disable(LOGGING)的使用
    Visual Studio 2010 Beta版包括InstallShield Limited Edition
    AdminStudio 9.5已经发布
    推荐一个修改MSI安装包和Merge Module的工具 Orca
    如何修改安装包程序的产品描述和版权信息
    InstallShield浮动License介绍
  • 原文地址:https://www.cnblogs.com/ShuraK/p/10536838.html
Copyright © 2011-2022 走看看