bzoj 3998: [TJOI2015]弦论
作者:互联网
可重复与不可重复的第k小串
/************************************************************** Problem: 3998 User: lxy8584099 Language: C++ Result: Accepted Time:5868 ms Memory:126324 kb ****************************************************************/ // luogu-judger-enable-o2 #include<cstdio> #include<cstring> using namespace std; const int N=5e5+50; struct Point {int fa,len,ch[26];} d[N<<1]; int tot=1,last=1,n,k,p,a[N<<1],b[N<<1],size[N<<1],sum[N<<1]; char s[N]; void insert(int c) { int x=last,nx=last=++tot; d[nx].len=d[x].len+1; size[nx]=1; for(;x&&!d[x].ch[c];x=d[x].fa) d[x].ch[c]=nx; if(!x) d[nx].fa=1; else { int y=d[x].ch[c]; if(d[y].len==d[x].len+1) d[nx].fa=y; else { int ny=++tot; d[ny]=d[y]; d[ny].len=d[x].len+1; d[y].fa=d[nx].fa=ny; for(;x&&d[x].ch[c]==y;x=d[x].fa) d[x].ch[c]=ny; } } } int main() { scanf("%s",s+1); n=strlen(s+1); scanf("%d%d",&k,&p); for(int i=1;i<=n;i++) insert(s[i]-'a'); for(int i=1;i<=tot;i++) b[d[i].len]++; for(int i=1;i<=tot;i++) b[i]+=b[i-1]; for(int i=1;i<=tot;i++) a[b[d[i].len]--]=i; // 以上三行操作将反拓扑序存入了数组里 for(int i=tot;i>=1;i--) if(k) size[d[a[i]].fa]+=size[a[i]]; else size[a[i]]=1; // 如果k=0,本质相同的子串在不同位置出现算相同,所以size[i]=1 // 否则就为endpos集合的大小 即该次 以及之后 会出现多少次 size[1]=0; // 记得把根节点的size变为0 for(int i=tot;i>=1;i--) { sum[a[i]]=size[a[i]]; for(int j=0;j<26;j++) if(d[a[i]].ch[j]) sum[a[i]]+=sum[d[a[i]].ch[j]]; } if(p>sum[1]) {puts("-1");return 0;} int u=1; p-=size[1]; while(p>0) { int l=0; while(p>sum[d[u].ch[l]]) p-=sum[d[u].ch[l++]]; u=d[u].ch[l]; putchar('a'+l); p-=size[u]; } putchar('\n'); return 0; }
标签:ch,return,int,弦论,TJOI2015,3998,sum,size 来源: https://www.cnblogs.com/lxy8584099/p/10416520.html