spoj7258 Lexicographical Substring Search(SUBLEX),后缀自动机

来源:互联网 发布:日本历史地震数据统计 编辑:程序博客网 时间:2024/05/19 05:04
spoj7258. Lexicographical Substring Search

求一个串的所有不同子串中字典序第k大的。

利用后缀自动机,拓扑排序后通过子边dp,可以计算当前状态可接受的后缀还有多少个串。
然后不断转移即可。

由于卡常数,需要两个优化:
1.预处理将空儿子去掉,减少转移复杂度。
2.优化输出,将要输出的串保存在一个char数组中,最后一起输出。会比一个字符一个字符快些。

最后吐槽一句,SPOJ这破评测机……

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define Maxn 90009int root,last;//samint tots;int fi[Maxn*2],ne[510000],to[510000],al[510000];int te;int tot[Maxn*2];char str[Maxn];struct sam_node{    int fa,son[26];    int len;    void init(int _len){len=_len;fa=-1;memset(son,-1,sizeof(son));}}t[Maxn*2];//length*2void sam_init(){    tots=0;    root=last=0;    t[tots].init(0);}void extend(int w){    //int w=ch-'a';    int p=last;    int np=++tots;t[tots].init(t[p].len+1);    int q,nq;    while(p!=-1&&t[p].son[w]==-1){t[p].son[w]=np;p=t[p].fa;}    if (p==-1) t[np].fa=root;    else{        q=t[p].son[w];        if (t[p].len+1==t[q].len){t[np].fa=q;}        else{            nq=++tots;t[nq].init(0);            t[nq]=t[q];            t[nq].len=t[p].len+1;            t[q].fa=nq;t[np].fa=nq;            while(p!=-1&&t[p].son[w]==q){t[p].son[w]=nq;p=t[p].fa;}        }    }    last=np;}int w[Maxn],r[Maxn*2],l;void topsort(){    int i;    for(i=0;i<=l;++i)   w[i]=0;    for(i=1;i<=tots;++i)w[t[i].len]++;    for(i=1;i<=l;++i)   w[i]+=w[i-1];    for(i=tots;i>=1;--i)r[w[t[i].len]--]=i;}void work(int k){    int i;    int p=root,tmp;    int e,tl;    tl=0;    while(--k){        for(e=fi[p];~e;e=ne[e]){            tmp=tot[to[e]];            if (tmp>=k) {p=to[e];str[tl++]=al[e]+'a';break;}            else {k-=tmp;}        }    }    str[tl]='\0';    puts(str);}inline void addedge(int u,int v,int j){    te++;    ne[te]=fi[u];fi[u]=te;to[te]=v;al[te]=j;}char s[Maxn];int i,u,ttot,j,q,k;int main(){    scanf("%s",s);    sam_init();    l=strlen(s);    for(i=0;i<l;++i){        extend(s[i]-'a');    }    topsort();    for(i=0;i<=tots;++i) fi[tots]=-1;    te=0;    r[0]=0;    for(i=tots;i>=0;--i){        u=r[i];        ttot=1;        for(j=25;j>=0;--j){            if (~t[u].son[j]) {                ttot+=tot[t[u].son[j]];                addedge(u,t[u].son[j],j);            }        }        tot[u]=ttot;    }    scanf("%d",&q);    for(i=1;i<=q;++i){        scanf("%d",&k);        work(k+1);    }    return 0;}



0 0
原创粉丝点击