zoukankan      html  css  js  c++  java
  • BZOJ_2434

    fail树上建可持久化树。

    根据原题中给定的输入跑就可以跑出一颗trie树,然后对这个trie数建fail树。我最开始的思路错了:A串在B串中出现的次数就是看B中有多少节点可以直接或者说间接的指向A的子树。举个反例:A = aaa,设A的子树是一个点为b,B = aaab,那么B将会有两个指针指向A的子树,出错了。正确姿势应该是对fail树的DFS序修改,我的做法是可持久化,在AC自动机上的树跑DFS,每到一个点对它的fail的子树进行区间修改,查询的时候就查询子树和就好了(我真是太蠢了)

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    using namespace std;
    const int N = 100003;
    char a[N];
    int t1,t2,q,haha1,haha2,biao[N];
    int first[N],to[N*2],next_[N*2],eg;
    inline void addedge(int x,int y) {
        next_[++eg] = first[x];
        first[x] = eg;
        to[eg] = y;
    }
    struct AC {
        AC* fail;
        AC* ch[26];
        AC* pre;
        int key;
        AC() {
            for(int i = 0 ; i < 26 ; ++i) ch[i] = NULL;
            pre = fail = NULL;
            key = 0;
        }
    }*R,dizhi1[N],*bfs[N];
    struct tree1 {
        tree1* lson;
        tree1* rson;
        int sum;
        tree1() {
            lson = rson = NULL;
            sum = 0;
        }
    }*root[N],dizhi2[N*20];
    inline void get_fail() {
        bfs[1] = R;
        int h = 0 , t = 1;
        do {
            AC* u = bfs[++h];
            for(int i = 0 ; i < 26 ; ++i) {
                if(u->ch[i]==NULL) continue;
                if(u==R) {
                    u->ch[i]->fail = R;
                    addedge(R->key,u->ch[i]->key);
                    bfs[++t] = u->ch[i];
                    continue;
                }
                AC* temp = u->fail;
                while(temp!=R&&temp->ch[i]==NULL) temp = temp->fail;
                if(temp->ch[i]!=NULL) {
                    u->ch[i]->fail = temp->ch[i];
                    addedge(temp->ch[i]->key,u->ch[i]->key);
                } else {
                    u->ch[i]->fail = R;
                    addedge(R->key,u->ch[i]->key);
                }
                bfs[++t] = u->ch[i];
            }
        }while(h<t);
    }
    int st[N],ed[N],tt;
    inline void dfs(int u) {
        st[u] = ++tt;
        for(int i = first[u] ; i ; i = next_[i])
            dfs(to[i]);
        ed[u] = tt;
    }
    inline void insert(tree1* tree,int l,int r,int pos,tree1* last) {
        if(l==r) {
            tree->sum = last==NULL?1:last->sum+1;
            return;
        }
        int mid = (l+r) >>1;
        if(pos <= mid) {
            if(last!=NULL && last->rson!=NULL) tree->rson = last->rson;
            tree->lson = &dizhi2[++t2];
            if(last!=NULL && last->lson!=NULL) insert(tree->lson,l,mid,pos,last->lson);
            else insert(tree->lson,l,mid,pos,NULL);
        } else {
            if(last!=NULL && last->lson!=NULL) tree->lson = last->lson;
            tree->rson = &dizhi2[++t2];
            if(last!=NULL && last->rson!=NULL) insert(tree->rson,mid+1,r,pos,last->rson);
            else insert(tree->rson,mid+1,r,pos,NULL);
        }
        if(tree->lson!=NULL) tree->sum += tree->lson->sum;
        if(tree->rson!=NULL) tree->sum += tree->rson->sum;
    }
    inline void build(AC* u) {
        if(u!=R) {
            root[u->key] = &dizhi2[++t2];
            insert(root[u->key],1,haha2,st[u->key],root[u->pre->key]);
        }
        for(int i = 0 ; i < 26 ; ++i) 
            if(u->ch[i]!=NULL) build(u->ch[i]);
    }
    inline int query(tree1* tree,int l,int r,int x,int y) {
        if(x<=l && r<=y) return tree->sum;
        int mid = (l+r)>>1,q1 = 0,q2 = 0;
        if(!(y<l || mid<x) && tree->lson!=NULL) q1 = query(tree->lson,l,mid,x,y);
        if(!(y<mid+1||r<x) && tree->rson!=NULL) q2 = query(tree->rson,mid+1,r,x,y);
        return (q1+q2);
    }
    int main() {
        scanf("%s",a);
        int len = strlen(a);
        R = &dizhi1[++t1];
        R->key = ++haha2;
        AC* now = R;
        for(int i = 0 ; i < len ; ++i) {
            if(a[i]=='B') {
                now = now->pre;
                continue;
            }
            if(a[i]=='P') {
                biao[++haha1] = now->key;
                continue;
            }
            int to = a[i] - 'a';
            if(now->ch[to]==NULL) {
                now->ch[to] = &dizhi1[++t1];
                now->ch[to]->pre = now;
                now->ch[to]->key = ++haha2;
            }
            now = now->ch[to];
        }
        get_fail();
        dfs(R->key);
        build(R);
        scanf("%d",&q);
        for(int i = 1,x,y ; i <= q ; ++i) {
            scanf("%d%d",&x,&y);
            printf("%d
    ",query(root[biao[y]],1,haha2,st[biao[x]],ed[biao[x]]));
        }
    }
    View Code
  • 相关阅读:
    Python面向对象-类成员
    python面向对象-继承
    Linux 静态和动态添加路由
    Linux 添加虚拟网卡
    centos7源码包安装Mongodb,并设置开机自启动
    centos7配置静态ip地址
    Python开发【前端篇】JavaScript和Jquery
    Python爬虫【解析库之pyquery】
    Python爬虫 selenium
    Python爬虫【解析库之beautifulsoup】
  • 原文地址:https://www.cnblogs.com/registerzxr/p/5081774.html
Copyright © 2011-2022 走看看