bzoj 3998: [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
 
 
 

构建出SAM之后,求出sum[i],表示有sum[i]个子串经过i号点

siz[i]表示ii所代表的Endpos的集合大小,也就是i所对应字符串集合的出现次数

T=0时,本质相同的子串在不同位置出现算相同,所以siz[i]=1,即将每个字符串集合的Endpos集合大小(字符串集合元素出现次数)置为1

T=1时,本质相同的子串在不同位置出现算不同,那么累加后的siz表示实际上Endpos的集合大小

 1 #include<bits/stdc++.h>
 2 using namespace std;  
 3 int const N=500000+1000;  
 4 struct node{
 5     int len,fa,ch[26];  
 6     node() { memset(ch,0,sizeof(ch)); len=0;  } 
 7 }a[N<<1];  
 8 char s[N];  
 9 long long sum[N<<1];  
10 int sz[N<<1],t,k,n,ls=1,tot=1,num[N],sa[N<<1];  
11 void add(int c){
12     int p=ls;  
13     int np=ls=++tot; 
14     sz[tot]=1;    
15     a[np].len=a[p].len+1;  
16     for(;p&&!a[p].ch[c]; p=a[p].fa) a[p].ch[c]=np;  
17     if(!p)  a[np].fa=1;  
18     else {
19         int q=a[p].ch[c];  
20         if(a[q].len==a[p].len+1)  a[np].fa=q; 
21         else {
22             int nq=++tot;  a[nq]=a[q];  
23             a[nq].len=a[p].len+1;  
24             a[q].fa=a[np].fa=nq;  
25             for(;p && a[p].ch[c]==q; p=a[p].fa) a[p].ch[c]=nq;  
26         } 
27     }
28 }
29 void dfs(int x,int k){
30     if(sz[x]>=k) return;  
31     k-=sz[x];  
32     for(int i=0;i<26;i++) {
33         int v=a[x].ch[i];  
34         if(!v) continue; 
35         if(k>sum[v]) {
36             k-=sum[v]; continue;    
37         }
38         putchar('a'+i); 
39         dfs(v,k);
40         return;  
41     }
42 } 
43 int main(){
44     scanf("%s",s);  
45     n=strlen(s);  
46     scanf("%d%d",&t,&k);  
47     for(int i=0;s[i];i++)   add(s[i]-'a');  
48     for(int i=1;i<=tot;i++) num[a[i].len]++;  
49     for(int i=1;i<=n;i++)   num[i]+=num[i-1];  
50     for(int i=1;i<=tot;i++) sa[num[a[i].len]--]=i;  
51     for(int i=tot;i>=1;i--) sz[a[sa[i]].fa]+=sz[sa[i]];  
52     for(int i=1;i<=tot;i++) 
53         if(t==0) sum[i]=sz[i]=1;  
54         else sum[i]=sz[i];  
55     sum[1]=sz[1]=0;  
56     for(int i=tot;i>=1;i--)  
57         for(int j=0;j<26;j++)  
58             if(a[sa[i]].ch[j]) sum[sa[i]]+=sum[a[sa[i]].ch[j]];  
59     if(sum[1]<k) puts("-1");  
60     else dfs(1,k);   
61     return 0; 
62 }    
View Code

 

posted @ 2019-06-14 15:09  zjxxcn  阅读(150)  评论(0编辑  收藏  举报