• bzoj3998 [TJOI2015]弦论


    Description

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

    Input

    第一行是一个仅由小写英文字母构成的字符串S

    第二行为两个整数T和K,T为0则表示不同位置的相同子串算作一个。T=1则表示不同位置的相同子串算作多个。K的意义如题所述。

    Output

    输出仅一行,为一个数字串,为第K小的子串。如果子串数目不足K个,则输出-1

    Sample Input

    aabc
    0 3

    Sample Output

    aab

    HINT 

    N<=5*10^5

    T<2
    K<=10^9

    正解:后缀自动机。

    我们可以使用后缀自动机来求出每一个后缀,那么可以知道,一个字符串的出现次数就是它的$right$集合大小,也就是它在后缀自动机的$parent$树上的子树大小。

    那么如果$T=1$,就把一个点的$sz$统计成它的$parent$子树,否则它的$sz$就是$1$,然后我们贪心地找出第$k$小子串就行了。

     1 #include <bits/stdc++.h>
     2 #define il inline
     3 #define RG register
     4 #define ll long long
     5 #define N (1000010)
     6 
     7 using namespace std;
     8 
     9 int ch[N][26],l[N],fa[N],sz[N],sum[N],c[N],id[N],n,t,k,la,tot,len;
    10 char s[N];
    11 
    12 il void add(RG int c){
    13   RG int p=la,np=++tot; la=np,l[np]=l[p]+1,sz[np]=1;
    14   for (;p && !ch[p][c];p=fa[p]) ch[p][c]=np;
    15   if (!p){ fa[np]=1; return; } RG int q=ch[p][c];
    16   if (l[q]==l[p]+1) fa[np]=q; else{
    17     RG int nq=++tot; l[nq]=l[p]+1;
    18     fa[nq]=fa[q],fa[q]=fa[np]=nq;
    19     memcpy(ch[nq],ch[q],sizeof(ch[q]));
    20     for (;ch[p][c]==q;p=fa[p]) ch[p][c]=nq;
    21   }
    22   return;
    23 }
    24 
    25 il void dfs(RG int x,RG int k){
    26   if (k<=sz[x]) return; RG int c=sz[x];
    27   for (RG int i=0;i<26;++i)
    28     if (k<=c+sum[ch[x][i]]){
    29       putchar('a'+i);
    30       return dfs(ch[x][i],k-c);
    31     } else c+=sum[ch[x][i]];
    32   return;
    33 }
    34 
    35 int main(){
    36 #ifndef ONLINE_JUDGE
    37   freopen("kth.in","r",stdin);
    38   freopen("kth.out","w",stdout);
    39 #endif
    40   scanf("%s",s+1),len=strlen(s+1),cin>>t>>k,tot=la=1;
    41   for (RG int i=1;i<=len;++i) add(s[i]-'a');
    42   for (RG int i=1;i<=tot;++i) ++c[l[i]];
    43   for (RG int i=1;i<=tot;++i) c[i]+=c[i-1];
    44   for (RG int i=1;i<=tot;++i) id[c[l[i]]--]=i;
    45   if (t) for (RG int i=tot;i;--i) sz[fa[id[i]]]+=sz[id[i]];
    46   else for (RG int i=tot;i;--i) sz[id[i]]=1; sz[1]=0;
    47   for (RG int i=tot;i;--i){
    48     sum[id[i]]=sz[id[i]];
    49     for (RG int j=0;j<26;++j)
    50       sum[id[i]]+=sum[ch[id[i]][j]];
    51   }
    52   if (sum[1]<k) puts("-1"); else dfs(1,k); return 0;
    53 }
  • 相关阅读:
    [CISCN2019 华北赛区 Day1 Web2]ikun
    [BJDCTF 2nd]简单注入
    [BJDCTF2020]ZJCTF,不过如此
    [BJDCTF2020]The mystery of ip
    [SWPU2019]Web1
    [WesternCTF2018]shrine
    [BJDCTF 2nd]假猪套天下第一
    [BJDCTF2020]Mark loves cat
    [GWCTF 2019]我有一个数据库
    C语言学习笔记_函数与函数库
  • 原文地址:https://www.cnblogs.com/wfj2048/p/7630221.html
Copyright © 2020-2023  润新知