zoukankan      html  css  js  c++  java
  • 【51nod1006】simple 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
    ",ans);
            for(int j=u;j;j=fa[top[j]])T.optadd(1,1,sam.cnt,tpos[top[j]],tpos[j]);
            p=u;
        }
    }
  • 相关阅读:
    python 下载文件保存到本地
    python 模拟udp客户端发送报文
    Block的底层代码实现
    常见的崩溃问题和类型
    NSTimer打破循环引用的几种方式
    springcloud alibaba Nacos解决OpenFeign调用失败问题
    LRU算法
    常见算法题解
    PHP无文件木马
    c++各种类型的字节数
  • 原文地址:https://www.cnblogs.com/zcysky/p/7500483.html
Copyright © 2011-2022 走看看