BZOJ3998: [TJOI2015]弦论
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3998
讲道理是一道很水的后缀自动机的题目,后缀自动机+第K大而已。
但像我这种蒟蒻,膜拜hzwer学长的博客膜了好久才改出来。
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #define inf 1<<30 5 #define maxn 500005 6 using namespace std; 7 int t,k,n; 8 char s[maxn]; 9 struct sam{ 10 int last,tot,par[maxn*2],val[maxn*2],sum[maxn*2],size[maxn*2],v[maxn],q[maxn*2],go[maxn*2][26]; 11 sam(){last=++tot;} 12 int newnode(int x){val[++tot]=val[x]+1;return tot;} 13 void extend(int x){ 14 int p=last,np=newnode(p); size[np]=1; 15 while(p&&go[p][x]==0) go[p][x]=np,p=par[p]; 16 if(p==0) par[np]=1; 17 else{ 18 int q=go[p][x]; 19 if(val[q]==val[p]+1) par[np]=q; 20 else{ 21 int nq=newnode(p); 22 memcpy(go[nq],go[q],sizeof(go[q])); 23 par[nq]=par[q]; par[q]=par[np]=nq; 24 while(p&&go[p][x]==q) go[p][x]=nq,p=par[p]; 25 } 26 } 27 last=np; 28 } 29 void calc(){ 30 for(int i=1;i<=tot;i++) v[val[i]]++; 31 for(int i=1;i<=n;i++) v[i]+=v[i-1]; 32 for(int i=tot;i;i--) q[v[val[i]]--]=i; 33 for(int i=tot;i;i--){ 34 if(t==1) size[par[q[i]]]+=size[q[i]]; 35 else size[q[i]]=1; 36 } 37 size[1]=0; 38 for(int i=tot;i;i--){ 39 sum[q[i]]=size[q[i]]; 40 for(int j=0;j<26;j++) sum[q[i]]+=sum[go[q[i]][j]]; 41 } 42 } 43 void dfs(int x,int y){ 44 if(y<=size[x]) return; 45 y-=size[x]; 46 for(int i=0;i<26;i++){ 47 if(go[x][i]==0) continue; 48 if(y<=sum[go[x][i]]){ 49 putchar(i+'a'); dfs(go[x][i],y); return; 50 } 51 y-=sum[go[x][i]]; 52 } 53 } 54 }sam; 55 int main(){ 56 scanf("%s",s+1); n=strlen(s+1); 57 scanf("%d%d",&t,&k); 58 for(int i=1;i<=n;i++) sam.extend(s[i]-'a'); 59 sam.calc(); 60 if(k>sam.sum[1]) puts("-1"); 61 else sam.dfs(1,k); 62 return 0; 63 }