Bzoj3998 弦论

来源:互联网 发布:金星舞蹈水平 知乎 编辑:程序博客网 时间:2024/06/10 13:35

物理题目传送门

求第k大的子串?SAM模板题啊

CLJ的论文都讲了怎么做啊,把自动机看成一个后缀Trie求出size让后像多叉平衡树那样乱搞就好了~

比前两个哈希的题好多了~ (顺便,hdu高亮好好看啊)

#pragma GCC opitmize("O3")#pragma G++ opitmize("O3")#include<stdio.h>#include<string.h>#include<algorithm>#define N 1000010using namespace std;char c[N];int s[N][26],mx[N],sz[N],f[N];int n,m,T,k,cnt=1,lst=1,v[N],r[N],w[N];inline int extend(int c){    int p=lst,np=lst=++cnt,q,nq;    mx[np]=mx[p]+1; sz[np]=1;    for(;p&&!s[p][c];p=f[p]) s[p][c]=np;    if(!p) return f[np]=1;    q=s[p][c];    if(mx[q]==mx[p]+1) f[np]=q;    else{        nq=++cnt;        mx[nq]=mx[p]+1;        f[nq]=f[q]; f[q]=f[np]=nq;        memcpy(s[nq],s[q],26<<2);        for(;p&&s[p][c]==q;p=f[p]) s[p][c]=nq;    }}inline void dfs(int x){    if(k<=sz[x]) return; else k-=sz[x];    for(int j=0;j<26;++j)        if(k>w[s[x][j]])k-=w[s[x][j]];        else { putchar(j+'a'); dfs(s[x][j]); break; }}int main(){    scanf("%s%d%d",c+1,&T,&k); n=strlen(c+1);    for(int i=1;i<=n;++i) extend(c[i]-'a');    for(int i=1;i<=cnt;++i) ++v[mx[i]];    for(int i=1;i<=n;++i) v[i]+=v[i-1];    for(int i=cnt;i;--i) r[v[mx[i]]--]=i;    if(T) for(int i=cnt;i;--i) sz[f[r[i]]]+=sz[r[i]];    else  for(int i=cnt;i;--i) sz[i]=1; sz[1]=*sz=0; memcpy(w,sz,sizeof w);    for(int i=cnt;i;--i) for(int j=0;j<26;++j) w[r[i]]+=w[s[r[i]][j]];    if(k>w[1]) puts("-1"); else dfs(1);}

原创粉丝点击