zoukankan      html  css  js  c++  java
  • BZOJ3998: [TJOI2015]弦论

    【传送门:BZOJ3998


    简要题意:

      对于一个给定长度为N的字符串,求它的第K小子串是什么


    题解:

      后缀自动机

      首先对于T=0的时候,所有的能到达的不同状态,Right集合大小恒为1

      T=1的时候,就累加

      然后先判断子串数量是否超过K

      如果没有,则直接DFS就好了


    参考代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<cstdlib>
    using namespace std;
    struct SAM
    {
        int son[27],dep,fail;
    }tr[1100000];int cnt,root,last;
    int a[510000];
    void add(int k)
    {
        int x=a[k];
        int np=++cnt,p=last;
        tr[np].dep=k;
        while(p!=0&&tr[p].son[x]==0) tr[p].son[x]=np,p=tr[p].fail;
        if(p==0) tr[np].fail=root;
        else
        {
            int q=tr[p].son[x];
            if(tr[q].dep==tr[p].dep+1) tr[np].fail=q;
            else
            {
                int nq=++cnt;tr[nq]=tr[q];
                tr[nq].dep=tr[p].dep+1;
                tr[q].fail=tr[np].fail=nq;
                while(p!=0&&tr[p].son[x]==q) tr[p].son[x]=nq,p=tr[p].fail;
            }
        }
        last=np;
    }
    char st[510000];
    int Rsort[510000],r[1100000],sum[1100000],sa[1100000];
    int k;
    void dfs(int x)
    {
        if(k<=r[x]) return ;
        k-=r[x];
        for(int i=1;i<=26;i++)
        {
            int y=tr[x].son[i];
            if(y==0) continue;
            if(k>sum[y]) k-=sum[y];
            else
            {
                printf("%c",i+'a'-1);
                dfs(y);
                return ;
            }
        }
    }
    int main()
    {
        scanf("%s",st+1);
        int len=strlen(st+1);
        cnt=last=root=1;
        for(int i=1;i<=len;i++) a[i]=st[i]-'a'+1,add(i);
        for(int i=1;i<=cnt;i++) Rsort[tr[i].dep]++;
        for(int i=1;i<=len;i++) Rsort[i]+=Rsort[i-1];
        for(int i=cnt;i>=1;i--) sa[Rsort[tr[i].dep]--]=i;
        int p=root;
        for(int i=1;i<=len;i++) p=tr[p].son[a[i]],r[p]++;
        int T;
        scanf("%d%d",&T,&k);
        for(int i=cnt;i>=1;i--)
        {
            if(T==0) r[tr[sa[i]].fail]=1;
            else r[tr[sa[i]].fail]+=r[sa[i]];
        }
        r[root]=0;
        for(int i=cnt;i>=1;i--)
        {
            int p=sa[i];sum[p]=r[p];
            for(int j=1;j<=26;j++) if(tr[p].son[j]!=0) sum[p]+=sum[tr[p].son[j]];
        }
        if(k>sum[root]) printf("-1");
        else dfs(root);
        printf("
    ");
        return 0;
    }

     

  • 相关阅读:
    U-Learning服务端
    C# 向txt文件中写入
    二维码生成 Gma.QrCodeNet (目前测试支持.net4.0及以上,但vs版本2010不可以 NuGet中搜索不到程序包)
    数据显示按规格向datatable中增加空白记录
    sql server 查询出整数 (可灵活运用)
    sql server 列字段拼接 —— STUFF
    layui confirm 嵌套使用 (随笔记)
    sql server 随记 -- 月份/日期 查询
    SQL Server 数据库备份语句
    关于ScriptManager.RegisterStartupScript 摘录
  • 原文地址:https://www.cnblogs.com/Never-mind/p/8805035.html
Copyright © 2011-2022 走看看