[bzoj3998][TJOI2015]弦論——後綴自動機
阿新 • • 發佈:2019-02-09
tjoi2015 back getchar() ont for () strlen 直接 clu
題目大意:
給定一個字符串,求它的第k小子串。
思路:
後綴自動機的模板題。
考慮將後綴自動機建出來之後,求出每一個狀態在原串中出現了多少次,然後統計以每個節點往後拓展的字符串總共有多少種(按照拓撲序累加即可),最後直接在DAG上做類似二分的就好了。
/*======================================= * Author : ylsoi * Time : 2019.2.9 * Problem : bzoj3998 * E-mail : [email protected] * ====================================*/ #include<bits/stdc++.h> #define REP(i,a,b) for(int i=a,i##_end_=b;i<=i##_end_;++i) #define DREP(i,a,b) for(int i=a,i##_end_=b;i>=i##_end_;--i) #define debug(x) cout<<#x<<"="<<x<<" " #define fi first #define se second #define mk make_pair #define pb push_back typedef long long ll; using namespace std; void File(){ freopen("bzoj3998.in","r",stdin); freopen("bzoj3998.out","w",stdout); } template<typename T>void read(T &_){ _=0; T f=1; char c=getchar(); for(;!isdigit(c);c=getchar())if(c=='-')f=-1; for(;isdigit(c);c=getchar())_=(_<<1)+(_<<3)+(c^'0'); _*=f; } const int maxn=5e5+10; int n,ty; ll m; char s[maxn]; struct Suffix_Automaton{ struct node{ int len,fa,ch[26]; }t[maxn<<1]; int last,tot; ll sz[maxn<<1],sum[maxn<<1]; Suffix_Automaton(){last=tot=1;} void insert(int x){ int p=last,np=last=++tot; sz[np]=1; t[np].len=t[p].len+1; while(p && !t[p].ch[x])t[p].ch[x]=np,p=t[p].fa; if(!p)t[np].fa=1; else{ int q=t[p].ch[x]; if(t[q].len==t[p].len+1)t[np].fa=q; else{ int nq=++tot; t[nq]=t[q],t[nq].len=t[p].len+1; t[q].fa=t[np].fa=nq; while(p && t[p].ch[x]==q)t[p].ch[x]=nq,p=t[p].fa; } } } int tax[maxn<<1],lis[maxn<<1]; void get_times(){ if(!ty)REP(i,2,tot)sz[i]=1; else{ REP(i,2,tot)++tax[t[i].len]; REP(i,1,n)tax[i]+=tax[i-1]; REP(i,2,tot)lis[tax[t[i].len]--]=i; DREP(i,tot-1,1)sz[t[lis[i]].fa]+=sz[lis[i]]; sz[1]=0; } } bool vis[maxn<<1]; void get_num(int o){ if(vis[o])return; vis[o]=1; sum[o]=sz[o]; REP(i,0,25){ int v=t[o].ch[i]; if(!v)continue; get_num(v); sum[o]+=sum[v]; } } void dfs(int o,ll k){ k-=sz[o]; if(k<=0)return; REP(i,0,25){ int v=t[o].ch[i]; if(!v)continue; if(k<=sum[v]){ printf("%c",'a'+i); dfs(v,k); break; } else k-=sum[v]; } } }T; int main(){ // File(); scanf("%s",s+1); read(ty),read(m); n=strlen(s+1); REP(i,1,n)T.insert(s[i]-'a'); T.get_times(); T.get_num(1); if(T.sum[1]<m)printf("-1"); else T.dfs(1,m); return 0; }
[bzoj3998][TJOI2015]弦論——後綴自動機