题意
给定一个长度为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 "); 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 }