• bzoj3998 [TJOI2015]弦论


    题目大意:

    求第k小的子串。

    解题方法:

    首先构建后缀自动机,通过拓扑排序求出每个子串的cnt(即该串的出现次数)。然后跑DFS,类似于平衡树求rank为k的数是什么的操作,如果当前指向的儿子(假装他是儿子)的cnt小于k,则k-=cnt,并转向下一个儿子。

    代码:

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 #include<iostream>
     7 #include<queue>
     8 #define ll long long
     9 #define del(a,b) memset(a,b,sizeof(a))
    10 using namespace std;
    11 const int MAXN=1e6+10;
    12 int op;
    13 int c[MAXN],a[MAXN];
    14 char s[MAXN];
    15 struct SAM
    16 {
    17     struct State
    18     {
    19         int ch[26],fa,val;
    20     }t[MAXN];
    21     int n,sz,root,last;
    22     int cnt[MAXN],sum[MAXN];
    23     int nw(int x){t[++sz].val=x;return sz;}
    24     void init()
    25     {
    26         sz=0;root=last=nw(0);
    27         del(cnt,0);del(sum,0);
    28     }
    29     void extend(int c)
    30     {
    31         int p=last,np=nw(t[p].val+1);
    32         for(;p&&!t[p].ch[c];p=t[p].fa) t[p].ch[c]=np;
    33         if(!p) t[np].fa=root;
    34         else
    35         {
    36             int q=t[p].ch[c];
    37             if(t[q].val==t[p].val+1) t[np].fa=q;
    38             else
    39             {
    40                 int nq=nw(t[p].val+1);
    41                 memcpy(t[nq].ch,t[q].ch,sizeof(t[q].ch));
    42                 t[nq].fa=t[q].fa;
    43                 t[q].fa=t[np].fa=nq;
    44                 for(;p&&t[p].ch[c]==q;p=t[p].fa) t[p].ch[c]=nq;
    45             }
    46         }
    47         cnt[np]=1;last=np;
    48     }
    49     void RadixSort()
    50     {
    51         del(c,0);
    52         for(int i=1;i<=sz;i++) c[t[i].val]++;
    53         for(int i=1;i<=n;i++) c[i]+=c[i-1];
    54         for(int i=sz;i>=1;i--) a[c[t[i].val]--]=i;
    55     }
    56     void get_pre()
    57     {
    58         for(int i=sz;i>=1;i--)
    59         if(op==1) cnt[t[a[i]].fa]+=cnt[a[i]];
    60         else cnt[a[i]]=1;
    61         cnt[1]=0;
    62         for(int i=sz;i>=1;i--)
    63         {
    64             sum[a[i]]=cnt[a[i]];
    65             for(int j=0;j<26;j++) sum[a[i]]+=sum[t[a[i]].ch[j]];
    66         }
    67     }
    68     void DFS(int x,int k)
    69     {
    70         if(k<=cnt[x]) return;
    71         k-=cnt[x];
    72         for(int i=0;i<26;i++)
    73         if(int to=t[x].ch[i])
    74         {
    75             if(k<=sum[to])
    76             {
    77                 putchar(i+'a');
    78                 DFS(to,k);return;
    79             }
    80             k-=sum[to];
    81         }
    82     }
    83 }sam;
    84 int main()
    85 {
    86     int k;sam.init();
    87     scanf("%s",s+1);
    88     sam.n=strlen(s+1);
    89     scanf("%d%d",&op,&k);
    90     for(int i=1;i<=sam.n;i++) sam.extend(s[i]-'a');
    91     sam.RadixSort();sam.get_pre();
    92     if(k>sam.sum[1]) puts("-1");
    93     else sam.DFS(1,k);
    94     return 0;
    95 }
  • 相关阅读:
    $Noip2018/Luogu5022$ 旅行
    $Noip2018/Luogu5020$ 货币系统 $dp$
    $Noip2018/Luogu5021$ 赛道修建 二分+树形
    $Noip2018/Luogu5019/Luogu1969$ 铺设道路
    $Poj1220/AcWing124 Number Base Convertion$ 进制转换+高精除
    $Poj1050 To the Max$
    $Poj1723/AcWing123 Soldiers$ 排序
    luogu质数距离
    模板线性筛
    CERC2016 bfs 最大生瓶颈边 lca
  • 原文地址:https://www.cnblogs.com/Oracle-LinJH/p/9687687.html
Copyright © 2020-2023  润新知