【BZOJ3998】弦论 【后缀自动机】

题意

  给定一个长度为n的字符串,求他的第k小子串是什么。

分析

T=0的时候,这个题跟SPOJ-SUBLEX的做法一样,当T=1的时候,不同位置的子串算多个,那么初始化的时候d[u]=cnt[u],没走一个字符不是k-1而是k-cnt[u]。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <iostream>
  4 #include <algorithm>
  5 
  6 using namespace std;
  7 const int maxn=1e6+5;
  8 char s[maxn];
  9 int n,T,k;
 10 
 11 struct state{
 12     int len,link;
 13     int next[26];
 14 }st[2*maxn];
 15 int last,cur,sz;
 16 int cnt[2*maxn],d[2*maxn],c[2*maxn];
 17 void init(){
 18     sz=1;
 19     last=cur=0;
 20     st[0].link=-1;
 21     st[0].len=0;
 22 //    memset(st[0].next,-1,sizeof(st[0].next));
 23 }
 24 
 25 void build_sam(int c){
 26     cur=sz++;
 27     st[cur].len=st[last].len+1;
 28     cnt[cur]=1;
 29 //    memset(st[cur].next,-1,sizeof(st[cur].next));
 30     int p;
 31     for(p=last;p!=-1&&st[p].next[c]==0;p=st[p].link){
 32         st[p].next[c]=cur;
 33     }
 34     if(p==-1)
 35         st[cur].link=0;
 36     else{
 37         int q=st[p].next[c];
 38         if(st[q].len==st[p].len+1)
 39             st[cur].link=q;
 40         else{
 41             int clone=sz++;
 42             st[clone].len=st[p].len+1;
 43             st[clone].link=st[q].link;
 44             for(int i=0;i<26;i++)
 45                 st[clone].next[i]=st[q].next[i];
 46             for(;p!=-1&&st[p].next[c]==q;p=st[p].link){
 47                 st[p].next[c]=clone;
 48             }
 49             st[q].link=st[cur].link=clone;
 50         }
 51     }
 52     last=cur;
 53 }
 54 int cmp(int a,int b){
 55     return st[a].len>st[b].len;
 56 }
 57 void solve(int k,int ty){
 58     if(d[0]<k){
 59         printf("-1\n");
 60         return ;
 61     }
 62     int u=0;
 63     while(k){
 64         for(int i=0;i<26;i++){
 65             int v=st[u].next[i];
 66             if(v==0)continue;
 67             if(k>d[v])
 68                 k-=d[v];
 69             else{
 70                 printf("%c",i+'a');
 71                 u=v;
 72                 if(ty==0)
 73                     k--;
 74                 else
 75                     k-=cnt[v];
 76                 break;
 77             }
 78         }
 79     }
 80 }
 81 void update(){
 82     for(int i=1;i<sz;i++){
 83         int o=c[i];
 84         for(int j=0;j<26;j++){
 85             int v=st[o].next[j];
 86             if(v==0)continue;
 87             d[o]+=d[v];
 88         }
 89     }
 90     for(int i=0;i<26;i++){
 91         int v=st[0].next[i];
 92         if(v==0)continue;
 93             d[0]+=d[v];
 94     }
 95 }
 96 
 97 int main(){
 98     scanf("%s",s);
 99     n=strlen(s);
100     init();
101     for(int i=0;i<n;i++)
102         build_sam(s[i]-'a');
103     for(int i=0;i<sz;i++)
104         c[i]=i;
105     sort(c+1,c+sz,cmp);
106     scanf("%d%d",&T,&k);
107     if(T==0){
108         for(int i=1;i<sz;i++)
109             d[i]=1;
110         update();
111         solve(k,0);
112     }else{
113         for(int i=1;i<sz;i++){
114             int o=c[i];
115             if(st[o].link!=-1){
116                 cnt[st[o].link]+=cnt[o];
117             }
118         }
119         for(int i=1;i<sz;i++)
120             d[i]=cnt[i];
121         update();
122         solve(k,1);
123     }
124 return 0;
125 }
View Code

 

posted @ 2018-11-01 11:08  蒟蒻LQL  阅读(320)  评论(0编辑  收藏  举报