标签:
求本质不同的第k小子串:
求出后缀数组,从0开始扫到n-1,到sa[i]为止一共有sum[i]个本质不同的子串
sum[i]=sum[i-1]+n-sa[i]-height[i]
直到sum[i]>=k为止
求第k小子串:
构造后缀树,设f[x]表示以x为前缀的子串数目,g[x]表示以x为前缀的后缀数目
查询时从根开始一路往下分治即可
#include<cstdio>
#include<cstring>
#define N 1000010
typedef long long ll;
char s[N];int n,i,j,k,T,K;
namespace Suffixarray{
int S[N],SA[N],rank[N],height[N],sum,pre;
inline bool leq(int a1,int a2,int b1,int b2){return a1<b1||a1==b1&&a2<=b2;}
inline bool leq(int a1,int a2,int a3,int b1,int b2,int b3){return a1<b1||a1==b1&&leq(a2,a3,b2,b3);}
inline void radixPass(int*a,int*b,int*r,int n,int K){
int*c=new int[K+1];
int i,sum,t;
for(i=0;i<=K;i++)c[i]=0;
for(i=0;i<n;i++)c[r[a[i]]]++;
for(i=sum=0;i<=K;i++)t=c[i],c[i]=sum,sum+=t;
for(i=0;i<n;i++)b[c[r[a[i]]]++]=a[i];
delete[]c;
}
void suffixArray(int*T,int*SA,int n,int K){
int n0=(n+2)/3,n1=(n+1)/3,n2=n/3,n02=n0+n2;
int*R=new int[n02+3];R[n02]=R[n02+1]=R[n02+2]=0;
int*SA12=new int[n02+3];SA12[n02]=SA12[n02+1]=SA12[n02+2]=0;
int*R0=new int[n0];
int*SA0=new int[n0];
int i,j,name=0,c0=-1,c1=-1,c2=-1,p=0,t=n0-n1,k=0;
for(i=j=0;i<n+n0-n1;i++)if(i%3)R[j++]=i;
radixPass(R,SA12,T+2,n02,K),radixPass(SA12,R,T+1,n02,K),radixPass(R,SA12,T,n02,K);
for(i=0;i<n02;i++){
if(T[SA12[i]]!=c0||T[SA12[i]+1]!=c1||T[SA12[i]+2]!=c2)name++,c0=T[SA12[i]],c1=T[SA12[i]+1],c2=T[SA12[i]+2];
if(SA12[i]%3==1)R[SA12[i]/3]=name;else R[SA12[i]/3+n0]=name;
}
if(name<n02)for(suffixArray(R,SA12,n02,name),i=0;i<n02;i++)R[SA12[i]]=i+1;else for(i=0;i<n02;i++)SA12[R[i]-1]=i;
for(i=j=0;i<n02;i++)if(SA12[i]<n0)R0[j++]=3*SA12[i];
for(radixPass(R0,SA0,T,n0,K);k<n;k++){
#define GetI() (SA12[t]<n0?SA12[t]*3+1:(SA12[t]-n0)*3+2)
i=GetI(),j=SA0[p];
if(SA12[t]<n0?leq(T[i],R[SA12[t]+n0],T[j],R[j/3]):leq(T[i],T[i+1],R[SA12[t]-n0+1],T[j],T[j+1],R[j/3+n0])){
SA[k]=i;
if(++t==n02)for(k++;p<n0;p++,k++)SA[k]=SA0[p];
}else{
SA[k]=j;
if(++p==n0)for(k++;t<n02;t++,k++)SA[k]=GetI();
}
}
delete[]R;delete[]SA12;delete[]SA0;delete[]R0;
}
void work(){
for(i=0;i<n;i++)S[i]=s[i]-‘a‘+1;
suffixArray(S,SA,n,26);
for(i=0;i<n;i++)rank[SA[i]]=i;
for(k=i=0;i<n;i++)if(rank[i]==n-1)k=0;
else{
if(k)k--;
for(j=SA[rank[i]+1];S[i+k]==S[j+k];k++);
height[rank[i]]=k;
}
for(i=0;i<n;pre=sum,i++){
sum=pre+n-SA[i];
if(i)sum-=height[i-1];
if(sum>=K){
j=K-pre;
if(i)j+=height[i-1];
for(k=0;k<j;k++)putchar(s[SA[i]+k]);
return;
}
}
puts("-1");
}
}
namespace Suffixtree{
const int inf=1<<25,S=28;
int text[N],root,last,pos,need,remain,acnode,ace,aclen;
int i,j,k,x,y,q[N],tot,g[N];ll f[N];
inline int min(int a,int b){return a<b?a:b;}
struct node{int st,en,lk,son[S];inline int len(){return min(en,pos)-st;}}tree[N];
inline int new_node(int st,int en=inf){return tree[++last].st=st,tree[last].en=en,last;}
inline int acedge(){return text[ace];}
inline void addedge(int node){
if(need)tree[need].lk=node;
need=node;
}
inline bool down(int node){
if(aclen>=tree[node].len())return ace+=tree[node].len(),aclen-=tree[node].len(),acnode=node,1;
return 0;
}
inline void init(){
need=last=remain=ace=aclen=0;
root=acnode=new_node(pos=-1,-1);
}
inline void extend(int c){
text[++pos]=c;need=0;remain++;
while(remain){
if(!aclen)ace=pos;
if(!tree[acnode].son[acedge()])tree[acnode].son[acedge()]=new_node(pos),addedge(acnode);
else{
int nxt=tree[acnode].son[acedge()];
if(down(nxt))continue;
if(text[tree[nxt].st+aclen]==c){aclen++;addedge(acnode);break;}
int split=new_node(tree[nxt].st,tree[nxt].st+aclen);
tree[acnode].son[acedge()]=split;
tree[split].son[c]=new_node(pos);
tree[nxt].st+=aclen;
tree[split].son[text[tree[nxt].st]]=nxt;
addedge(split);
}
remain--;
if(acnode==root&&aclen)aclen--,ace=pos-remain+1;
else acnode=tree[acnode].lk?tree[acnode].lk:root;
}
}
void dfs(int x){
if(tree[x].en==inf)f[x]=g[x]=1;
for(int i=0;i<S;i++)if(tree[x].son[i]){
int y=tree[x].son[i];
dfs(y),f[x]+=f[y]+(ll)tree[y].len()*g[y],g[x]+=g[y];
}
}
void work(){
init();
for(i=0;i<n;i++)extend(s[i]-‘a‘+1);extend(27);
dfs(x=root);
while(1){
if(x!=root&&(ll)tree[x].len()*g[x]>=K){
for(j=1;j<tot;j++)for(k=tree[q[j]].st;k<tree[q[j]].en;k++)putchar(text[k]+‘a‘-1);
for(K=(K-1)/g[x]+1,j=0;j<K;j++)putchar(text[tree[y].st+j]+‘a‘-1);
return;
}
for(K-=tree[x].len()*g[x],i=0;i<S;i++)if(tree[x].son[i]){
y=tree[x].son[i];
if(f[y]+(ll)(tree[y].len()-1)*g[y]>=K){q[++tot]=x=y;break;}else K-=f[y]+(ll)(tree[y].len()-1)*g[y];
}
}
}
}
int main(){
gets(s),scanf("%d%d",&T,&K),n=std::strlen(s);
if(K>(ll)n*(n+1)/2)return puts("-1"),0;
if(!T)Suffixarray::work();else Suffixtree::work();
return 0;
}
标签:
原文地址:http://www.cnblogs.com/clrs97/p/4444752.html