[K大子串 后缀自动机 模板题] BZOJ 3998 [TJOI2015]弦论
2017-01-28 21:09
453 查看
题目大意:分别求 重复子串算一次 重复子串算多次 的 K小子串
若重复子串算一次 那么每个状态计数1次
若重复子串算多次 那么每个状态计数|right(x)|次
然后跑就好了
若重复子串算一次 那么每个状态计数1次
若重复子串算多次 那么每个状态计数|right(x)|次
然后跑就好了
#include<cstdio> #include<cstdlib> #include<algorithm> using namespace std; inline char nc(){ static char buf[100000],*p1=buf,*p2=buf; if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; } return *p1++; } inline void read(int &x){ char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b; } inline int read(char *s){ char c=nc(); int len=0; for (;!(c>='a' && c<='z');c=nc()) if (c==EOF) return 0; for (;c>='a' && c<='z';s[++len]=c,c=nc()); s[++len]=0; return len-1; } const int N=500005; struct state{ int len,link,next[26]; }st[N<<1]; int ncnt,last; int cnt[2][N<<1],size[2][N<<1]; inline void Extend(char c){ int cur=++ncnt,p; c-='a'; st[cur].len=st[last].len+1; cnt[1][cur]=1; size[1][cur]=1; for (p=last;p!=-1 && !st[p].next[c];p=st[p].link) st[p].next[c]=cur; if (p==-1) st[cur].link=0; else{ int q=st[p].next[c]; if (st[q].len==st[p].len+1) st[cur].link=q; else{ int nq=++ncnt; st[nq].len=st[p].len+1; st[nq].link=st[q].link; for (int i=0;i<26;i++) st[nq].next[i]=st[q].next[i]; for (;p!=-1 && st[p].next[c]==q;p=st[p].link) st[p].next[c]=nq; st[q].link=st[cur].link=nq; } } last=cur; } int tmp[N<<1],sum[N<<1]; inline void Sort(){ for (int i=0;i<=ncnt;i++) sum[st[i].len]++; for (int i=1;i<=st[last].len;i++) sum[i]+=sum[i-1]; for (int i=0;i<=ncnt;i++) tmp[sum[st[i].len]--]=i; } char A ; int na; char ans ; int len=0; inline void Solve(int *cnt,int *size,int K){ if (K>size[0]){ printf("-1\n"); return; } int p=0; len=0; while (1){ if (K<=cnt[p]) break; K-=cnt[p]; for (int i=0;i<26;i++) if (st[p].next[i]){ if (K<=size[st[p].next[i]]){ p=st[p].next[i]; ans[++len]='a'+i; break; }else K-=size[st[p].next[i]]; } } ans[++len]=0; printf("%s\n",ans+1); } int main(){ int T,K; freopen("t.in","r",stdin); freopen("t.out","w",stdout); na=read(A); st[0].link=-1; for (int i=1;i<=na;i++) Extend(A[i]); Sort(); for (int i=ncnt+1;i;i--) if (tmp[i]) cnt[1][st[tmp[i]].link]+=cnt[1][tmp[i]]; cnt[1][0]=0; for (int i=1;i<=ncnt;i++) cnt[0][i]=1; for (int i=0;i<=ncnt;i++) size[0][i]=cnt[0][i]; for (int i=ncnt+1;i;i--) for (int j=0;j<26;j++) if (st[tmp[i]].next[j]) size[0][tmp[i]]+=size[0][st[tmp[i]].next[j]]; for (int i=0;i<=ncnt;i++) size[1][i]=cnt[1][i]; for (int i=ncnt+1;i;i--) for (int j=0;j<26;j++) if (st[tmp[i]].next[j]) size[1][tmp[i]]+=size[1][st[tmp[i]].next[j]]; read(T); read(K); Solve(cnt[T],size[T],K); return 0; }
相关文章推荐
- BZOJ 题目3998: [TJOI2015]弦论(后缀自动机求排名第k的子串,可重复)
- [BZOJ3998][TJOI2015]弦论 后缀自动机
- [BZOJ3998] [TJOI2015] 弦论 - 后缀自动机
- [BZOJ3998][TJOI2015]弦论 后缀自动机
- 【BZOJ3998】弦论(TJOI2015)-后缀自动机
- 【后缀自动机】 BZOJ 3998: [TJOI2015]弦论
- 【bzoj3998】[TJOI2015]弦论 后缀自动机+dp
- BZOJ_3998_[TJOI2015]弦论_后缀自动机
- bzoj 3998: [TJOI2015]弦论 (后缀自动机)
- bzoj 3998: [TJOI2015]弦论 后缀自动机
- bzoj3998 [TJOI2015]弦论 后缀自动机
- [BZOJ3998]TJOI2015弦论|后缀自动机
- BZOJ 3998 [TJOI2015]弦论【后缀自动机(总结+安利
- [BZOJ3998][TJOI2015]弦论(后缀自动机)
- 【bzoj3998】[TJOI2015]弦论 后缀自动机
- [BZOJ3998][TJOI2015]弦论(后缀自动机+拓扑排序+贪心)
- [BZOJ3998][TJOI2015]弦论(后缀自动机)
- 【BZOJ3998】【TJOI2015】弦论 后缀自动机
- [bzoj3998][TJOI2015]弦论-后缀自动机
- [BZOJ3998][TJOI2015]弦论(后缀自动机)