51nod1006simple KMP

Posted zcysky

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51nod1006simple KMP相关的知识,希望对你有一定的参考价值。

原题意看的挺迷糊的,后来看了http://blog.csdn.net/YxuanwKeith/article/details/52351335大爷的题意感觉清楚的多……

做法也非常显然了,用树剖维护后缀自动机的parent树。

修改操作看成对每一个状态的right集合全都访问次数+1

询问同理。

然后我忘了更新爬后缀树时候的新状态调了挺久的。。。。。

因为这么傻逼的错误还能过样例。。。。。

#include<bits/stdc++.h>
const int N=2e5+10;
const int yql=1e9+7;
using namespace std;
int n,rt,tot=0,head[N],cnt;
int size[N],wson[N],tpos[N],top[N],fa[N],d[N],len,pre[N];
char s[N];
struct Edge{int u,v,next;}G[N<<1];
struct Suffix_AutoMaton{
    int ch[N<<1][26],fa[N<<1],l[N<<1],cnt,last;
    inline void init(){cnt=1;last=1;}
    inline void ins(int c){
        int p=last,np=++cnt;last=np;l[np]=l[p]+1;
        for(;p&&!ch[p][c];p=fa[p])ch[p][c]=np;
        if(!p)fa[np]=1;
        else{
            int q=ch[p][c];
            if(l[p]+1==l[q])fa[np]=q;
            else{
                int nq=++cnt;l[nq]=l[p]+1;
                memcpy(ch[nq],ch[q],sizeof(ch[q]));
                fa[nq]=fa[q];
                fa[np]=fa[q]=nq;
                for(;ch[p][c]==q;p=fa[p])ch[p][c]=nq;
            }
        }
    }
}sam;
inline void addedge(int u,int v){
    G[++tot].u=u;G[tot].v=v;G[tot].next=head[u];head[u]=tot;
    G[++tot].u=v;G[tot].v=u;G[tot].next=head[v];head[v]=tot;
}
inline void dfs1(int u,int f){
    size[u]=1;
    for(int i=head[u];i;i=G[i].next){
        int v=G[i].v;if(v==f)continue;
        fa[v]=u;d[v]=d[u]+1;
        dfs1(v,u);
        size[u]+=size[v];
        if(size[v]>size[wson[u]])wson[u]=v;
    }
}
inline void dfs2(int u,int tp){
    tpos[u]=++cnt;pre[cnt]=u;top[u]=tp;
    if(wson[u])dfs2(wson[u],tp);
    for(int i=head[u];i;i=G[i].next){
        int v=G[i].v;
        if(v==fa[u]||v==wson[u])continue;
        dfs2(v,v);
    }
}
struct Segment_Tree{
#define lson (o<<1)
#define rson (o<<1|1)
    int sumv[N<<2],size[N<<2],addv[N<<2];
    inline void pushup(int o){sumv[o]=(sumv[lson]+sumv[rson])%yql;}
    inline void pushdown(int o,int l,int r){
        if(!addv[o])return;
        addv[lson]+=addv[o];addv[rson]+=addv[o];
        sumv[lson]=(sumv[lson]+1LL*size[lson]*addv[o]%yql)%yql;
        sumv[rson]=(sumv[rson]+1LL*size[rson]*addv[o]%yql)%yql;
        addv[o]=0;
    }
    inline void build(int o,int l,int r){
        if(l==r){size[o]=sam.l[pre[l]]-sam.l[sam.fa[pre[l]]];return;}
        int mid=(l+r)>>1;
        build(lson,l,mid);build(rson,mid+1,r);
        size[o]=(size[lson]+size[rson])%yql;
    }
    inline int querysum(int o,int l,int r,int ql,int qr){
        if(ql<=l&&r<=qr)return sumv[o];
        int mid=(l+r)>>1,ans=0;
        pushdown(o,l,r);
        if(ql<=mid)ans=(ans+querysum(lson,l,mid,ql,qr))%yql;
        if(qr>mid)ans=(ans+querysum(rson,mid+1,r,ql,qr))%yql;
        return ans;
    }
    inline void optadd(int o,int l,int r,int ql,int qr){
        if(ql<=l&&r<=qr){addv[o]+=1;if(addv[o]>yql)addv[o]-=yql;sumv[o]=(sumv[o]+size[o])%yql;return;}
        int mid=(l+r)>>1;pushdown(o,l,r);
        if(ql<=mid)optadd(lson,l,mid,ql,qr);
        if(qr>mid)optadd(rson,mid+1,r,ql,qr);
        pushup(o);
    }
}T;
int main(){
    scanf("%d",&n);
    scanf("%s",s+1);sam.init();
    for(int i=1;i<=n;i++)sam.ins(s[i]-a);
    for(int i=1;i<=sam.cnt;i++)addedge(sam.fa[i],i);
    dfs1(1,0);dfs2(1,1);T.build(1,1,sam.cnt);
    int p=1,ans=0,cur=0;
    for(int i=1;i<=n;i++){
        int c=s[i]-a;int u=sam.ch[p][c];
        for(int j=u;j;j=fa[top[j]])cur=(cur+T.querysum(1,1,sam.cnt,tpos[top[j]],tpos[j]))%yql;
        ans=(ans+cur)%yql;printf("%d\n",ans);
        for(int j=u;j;j=fa[top[j]])T.optadd(1,1,sam.cnt,tpos[top[j]],tpos[j]);
        p=u;
    }
}

 

以上是关于51nod1006simple KMP的主要内容,如果未能解决你的问题,请参考以下文章

51Nod 1600 Simple KMP SAM+LCT/树链剖分

[51nod 1129] 字符串最大值(kmp)

51nod 1554 KMP?????????

51Nod 1006 1276 岛屿的数量

模板51nod 1006 最长公共子序列Lcs

51Nod-1006 最长公共子序列Lcs