[K大子串 后缀自动机 模板题] BZOJ 3998 [TJOI2015]弦论
来源:互联网 发布:linux 双网卡双网关 编辑:程序博客网 时间:2024/05/17 20:32
题目大意:分别求 重复子串算一次 重复子串算多次 的 K小子串
若重复子串算一次 那么每个状态计数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[N];int na;char ans[N]; 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;}
0 0
- [K大子串 后缀自动机 模板题] BZOJ 3998 [TJOI2015]弦论
- BZOJ 3998 TJOI2015 弦论 后缀自动机
- BZOJ 3998 TJOI2015 弦论 后缀自动机
- 【后缀自动机】 BZOJ 3998: [TJOI2015]弦论
- bzoj 3998: [TJOI2015]弦论 (后缀自动机)
- bzoj 3998: [TJOI2015]弦论 后缀自动机
- [BZOJ]3998 [TJOI2015] 弦论 后缀自动机
- bzoj 3998 [TJOI2015]弦论 后缀数组||后缀自动机
- BZOJ 题目3998: [TJOI2015]弦论(后缀自动机求排名第k的子串,可重复)
- BZOJ 3998 [TJOI2015]弦论【后缀自动机(总结+安利
- 3998: [TJOI2015]弦论 后缀自动机
- [BZOJ2555] [TJOI2015]弦论 && 后缀自动机
- 【BZOJ3998】【TJOI2015】弦论 后缀自动机
- [BZOJ3998]TJOI2015弦论|后缀自动机
- 【bzoj3998】[TJOI2015]弦论 后缀自动机
- 【BZOJ3998】【TJOI2015】 弦论 后缀自动机
- [BZOJ3998] [TJOI2015] 弦论 - 后缀自动机
- 【bzoj3998】[TJOI2015]弦论 后缀自动机
- Ubuntu下的截图工具
- View相关知识点
- 1032. Sharing (25)
- 关系数据库:概念理解 —— 范式
- maven 父子模块
- [K大子串 后缀自动机 模板题] BZOJ 3998 [TJOI2015]弦论
- Java 1.8 新特性之(Lambda表达式)
- 创建二叉树,并先序遍历
- 【IMX6UL开发板试用体验】OpenWRT有线网络的配置
- c++判断文件编码格式
- SPOJ-GSS7 Can you answer these queries VII(树上区间最大和)
- AsyncTask的源码分析,非常详细!
- Servlet之ServletContext创建对象和作用
- 12c Oracle_Home下的监听器监听11g数据库的问题