bzoj3998 [TJOI2015]弦论 后缀自动机
2017-07-24 10:36
295 查看
经典的求k小子串的问题。
根据right集合的定义,如果是相同子串不同位置算作一个,那每一个right集合对应的左右区间长度的大小就是这个right集合所包含的不同子串个数。
但是知道了这个并不代表我们可以直接求出来= =因为你并不知道k小是right集合中的哪一个,也就是说你没有办法准确的用尽量小的复杂度去把这个K小的子串拿出来,所以我们只能在dag上搞事情。。
设sum[i]表示以i为根时子树不同的子串个数。
那么有f[i]=sigma(f[son])+num[i]
num[i]表示以i为根时i这个节点对f的贡献。
那么明显当不算重复时num[i]=1否则num[i]就是i这个节点伸出的边数。
然后dfs一遍像主席树一样求个k大就好了。
根据right集合的定义,如果是相同子串不同位置算作一个,那每一个right集合对应的左右区间长度的大小就是这个right集合所包含的不同子串个数。
但是知道了这个并不代表我们可以直接求出来= =因为你并不知道k小是right集合中的哪一个,也就是说你没有办法准确的用尽量小的复杂度去把这个K小的子串拿出来,所以我们只能在dag上搞事情。。
设sum[i]表示以i为根时子树不同的子串个数。
那么有f[i]=sigma(f[son])+num[i]
num[i]表示以i为根时i这个节点对f的贡献。
那么明显当不算重复时num[i]=1否则num[i]就是i这个节点伸出的边数。
然后dfs一遍像主席树一样求个k大就好了。
#include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #define fo(i,a,b) for(int i=a;i<=b;i++) #define fd(i,a,b) for(int i=a;i>=b;i--) using namespace std; const int N=1e6+5; typedef long long ll; int cnt,tot,n,m,mx ; char s ; int ch [30],fa ; int f ,b ,last,c ,sum ; int T,k; void ins(int x) { int p,q,np,nq; p=last;last=np=++cnt;mx[np]=mx[p]+1;f[np]=1; for (;!ch[p][x]&&p;p=fa[p]) ch[p][x]=np; if (!p) fa[np]=1; else { q=ch[p][x]; if (mx[q]==mx[p]+1) fa[np]=q; else { nq=++cnt;mx[nq]=mx[p]+1; memcpy(ch[nq],ch[q],sizeof(ch[q])); fa[nq]=fa[q]; fa[q]=fa[np]=nq; for (;ch[p][x]==q;p=fa[p]) ch[p][x]=nq; } } } void pre() { for (int i=1;i<=cnt;i++) b[mx[i]]++; for (int i=1;i<=n;i++) b[i]+=b[i-1]; for (int i=1;i<=cnt;i++) c[b[mx[i]]--]=i; for (int i=cnt;i>=1;i--) { if (T==1) f[fa[c[i]]]+=f[c[i]]; else f[c[i]]=1; } f[1]=0; for (int i=cnt;i>=1;i--) { int t=c[i];sum[t]=f[t]; for (int j=0;j<26;j++) sum[t]+=sum[ch[t][j]]; } } inline void solve(int x,int k) { if (f[x]>=k)return; k-=f[x]; fo(i,0,25) if (ch[x][i]) { int t=ch[x][i]; if (sum[t]>=k) { putchar(i+'a'); solve(ch[x][i],k); return; } else k-=sum[t]; } } int main() { scanf("%s",s+1); n=strlen(s+1); cnt=last=1; fo(i,1,n)ins(s[i]-'a'); scanf("%d%d",&T,&k); pre(); if (k>sum[1])printf("-1"); else solve(1,k); return 0; }
相关文章推荐
- bzoj 3998: [TJOI2015]弦论 后缀自动机
- [BZOJ]3998 [TJOI2015] 弦论 后缀自动机
- [BZOJ3998]-[TJOI2015]弦论-后缀自动机
- 【BZOJ3998】【TJOI2015】弦论 后缀自动机
- [BZOJ3998][TJOI2015]弦论(后缀自动机)
- 【BZOJ3998】弦论(TJOI2015)-后缀自动机
- 【bzoj3998】[TJOI2015]弦论 后缀自动机
- [BZOJ3998][TJOI2015]弦论(后缀自动机+拓扑排序+贪心)
- BZOJ 3998 TJOI2015 弦论 后缀自动机
- BZOJ 3998: [TJOI2015]弦论 [后缀自动机 DP]
- [bzoj3998][TJOI2015]弦论-后缀自动机
- BZOJ 3998: [TJOI2015]弦论 后缀自动机
- BZOJ 3998 TJOI2015 弦论 后缀自动机
- BZOJ 3998 TJOI 2015 弦论 后缀自动机
- BZOJ 3998 [TJOI2015]弦论 ——后缀自动机
- [BZOJ3998]TJOI2015弦论|后缀自动机
- bzoj 3998: [TJOI2015]弦论 后缀自动机
- bzoj 3998 [TJOI2015]弦论 后缀数组||后缀自动机
- 【bzoj3998】[TJOI2015]弦论 后缀自动机+dp
- 【BZOJ3998】【TJOI2015】 弦论 后缀自动机