IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    BZOJ3881:[Coci2015]Divljak AC自动机+树链求并

    wyfcyx发表于 2015-03-06 11:18:58
    love 0

    思路:

    AC自动机的Fail树有很多奇妙的性质.

    例如串\(a\)是串\(b\)在Fail树上的祖先,那么\(a\)在\(b\)中应该出现\(dep[b]-dep[a]\)次.

    (不过好像跟这题没什么关系)

    把Alice的\(n\)个字符串插入AC自动机.

    然后每插入一个修改串,都动态维护一下每个自动机中的节点,如果出现在修改串中,则该节点答案+1.

    我们用修改串在自动机上走,每走到一个节点,我们都想要这个节点在Fail树上到根的路径上的答案均+1.

    遗憾的是,这样有可能重复!

    利用树链的并.

    将所有要处理的节点按照dfs序排序,然后首先把它们到根的路径+1.

    随后将相邻两个节点的LCA到根的路径-1.

    非常科学.

    怎么加?树链剖分?等TLE吧.

    直接将标记累加在节点上,询问时就询问子树内的标记之和.

    这样只需用树状数组维护DFS序即可.

    可惜卡常数!

    用倍增LCA会超时.

    于是我们换用RMQlca,并用ZKW线段树维护.

    估计ST表预处理也会超时.

    反正总算还是水过去了.

    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    using namespace std;
      
    #define N 2002010
    int ch[N][26],fail[N],ins[N],cnt;
    char s[N];
      
    int head[N],next[N],end[N];
    inline void addedge(int a,int b){
        static int q=1;end[q]=b,next[q]=head[a],head[a]=q++;
    }
      
    int in[N],out[N],dep[N],tclock;
    void dfs(int x){
        in[x]=++tclock;
        for(int j=head[x];j;j=next[j])
            dep[end[j]]=dep[x]+1,dfs(end[j]);
        out[x]=tclock;
    }
     
    namespace Lca_system{
        int Seq[N<<1],a[8383608],M,ins[N],cnt;
        inline void build_dfs(int x){
            ins[x]=++cnt;
            Seq[cnt]=x;
            for(int j=head[x];j;j=next[j]){
                build_dfs(end[j]);
                Seq[++cnt]=x;
            }
        }
        inline int Min(int x,int y){
            if(x==-1||y==-1)return x==-1?y:x;
            return dep[x]<<=1);
            memset(a,-1,sizeof a);
            for(int i=1;i<=cnt;++i)a[M+i]=Seq[i];
            for(int i=M-1;i>=1;--i)a[i]=Min(a[2*i],a[2*i+1]);
        }
        inline int ask(int tl,int tr){
            int re=-1;
            for(tl+=M-1,tr+=M+1;tl^tr^1;tl>>=1,tr>>=1){
                if(~tl&1)re=Min(re,a[tl^1]);
                if(tr&1)re=Min(re,a[tr^1]);
            }
            return re;
        }
        inline int lca(int x,int y){
            x=ins[x],y=ins[y];
            if(x>y)swap(x,y);
            return ask(x,y);
        }
    }
     
    int seq[N],num;
      
    int A[N];
    inline void modify(int x,int c){
        for(;x<=cnt+1;x+=x&-x)A[x]+=c;
    }
    inline int ask(int x){
        int re=0;for(;x;x-=x&-x)re+=A[x];return re;
    }
      
    inline bool cmp(const int&x;,const int&y;){return in[x]<<1)+(re<<3)+c-'0';
        return re;
    }
    char buf[100010*6],*o=buf;
    inline void print(int x){
        static int s[100];int top=0;
        if(!x)*o++=48;else{for(;x;x/=10)s[++top]=x%10;for(int i=top;i>=1;--i)*o++=48+s[i];}
        *o++='\n';
    }
    int main(){
        int n=git();
        register int i,j;
          
        int len,p;
        for(i=1;i<=n;++i){
            scanf("%s",s);
            len=strlen(s),p=0;
            for(j=0;jq;
        for(i=0;i<26;++i)if(ch[0][i])q.push(ch[0][i]);
        int u,v,r;
        while(!q.empty()){
            u=q.front(),q.pop();
            for(i=0;i<26;++i)if((v=ch[u][i])){
                q.push(v);
                for(r=fail[u];r&&!ch[r][i];r=fail[r]);
                fail[v]=ch[r][i];
            }
        }
          
        for(i=1;i<=cnt;++i)addedge(fail[i],i);
        dep[0]=1,dfs(0);
        Lca_system::init();
          
        int Q=git();
          
        int qte,x;
        while(Q--){
            qte=git();
            if(qte==1){
                scanf("%s",s);
                len=strlen(s),p=0,num=0;
                for(i=0;i<=num;++i)modify(in[seq[i]],1);
                for(i=1;i


沪ICP备19023445号-2号
友情链接