zoukankan      html  css  js  c++  java
  • bzoj 2434 AC自动机 + fail指针建树 + 树状数组

    思路:我们先跟着它给定的字符串走把字典树建出来,求出fail指针,我们考虑两个字符串 A和B,

    如果想要求B中有多少A的子串,转换一下就是有多少个B的前缀的后缀包含A,这个在AC自动机

    的状态图中很容易表示,就是字符串B所占的结点中 有多少个结点顺着fail能到达A的尾结点,

    并且fail构建出来的图是一棵树,转换成A的尾结点的子树中有多少个B的节点,用dfs序构建树状

    数组能很容易完成,又因为有m组询问,我们把询问离线排序,就能解决问题啦。

    #include<bits/stdc++.h>
    #define LL long long
    #define ll long long
    #define fi first
    #define se second
    #define mk make_pair
    #define PII pair<int, int>
    #define y1 skldjfskldjg
    #define y2 skldfjsklejg
    
    using namespace std;
    
    const int N = 2e5 + 7;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const int mod = 1000000007;
    
    int n, m, pos, ans[N], t[N];
    char s[N];
    
    struct Qus {
        int x, y, id;
        bool operator < (const Qus &rhs) const {
            return y < rhs.y;
        }
    } qus[N];
    
    struct BIT {
        int a[N];
        void modify(int x, int v) {
            for(int i = x; i < N; i += i & -i)
                a[i] += v;
        }
        int sum(int x) {
            int ans = 0;
            for(int i = x; i; i -= i & -i)
                ans += a[i];
            return ans;
        }
    } bit;
    
    struct Ac {
        int ch[N][26], val[N], dp[N], f[N], L[N], R[N], tot, sz, cnt, all;
        bool vis[N];
        vector<PII> vec[N];
        vector<int> edge[N];
    
        Ac(int sz) {this->sz = sz;}
        void init() {tot = 0;}
        int newNode() {
            tot++; f[tot] = 0; val[tot] = 0;
            memset(ch[tot], 0, sizeof(ch[tot]));
            return tot;
        }
        inline int idx(char c) {return c - 'a';}
        void addStr(char *s) {
            stack<int> stk;
            int u = 0;
            stk.push(0);
            for(int i = 0; s[i]; i++) {
                if(s[i] == 'P') {
                    cnt++; val[u]++; t[cnt] = u;
                    while(pos <= n && qus[pos].y <= cnt)
                        vec[u].push_back(mk(qus[pos].x, qus[pos].id)), pos++;
                } else if(s[i] == 'B') {
                    if(stk.size() > 1) {
                        stk.pop();
                        u = stk.top();
                    }
                } else {
                    int c = idx(s[i]);
                    if(!ch[u][c]) ch[u][c] = newNode();
                    u = ch[u][c];
                    stk.push(u);
                }
            }
        }
        
        void build() {
            queue<int> que;
            for(int c = 0; c < sz; c++) {
                int v = ch[0][c];
                if(!v) ch[0][c] = 0;
                else f[v] = 0, que.push(v);
            }
            while(!que.empty()) {
                int u = que.front(); que.pop();
                val[u] |= val[f[u]];
                for(int c = 0; c < sz; c++) {
                    int v = ch[u][c];
                    if(!v) ch[u][c] = ch[f[u]][c];
                    else f[v] = ch[f[u]][c], que.push(v);
                }
            }
        }
    
        void dfs(int u) {
            L[u] = ++all;
            for(int i = 0; i < edge[u].size(); i++) {
                int v = edge[u][i];
                dfs(v);
            }
            R[u] = all;
        }
    
        void solve(char *s) {
            for(int i = 1; i <= tot; i++)
                edge[f[i]].push_back(i);
    
            dfs(0);
    
            stack<int> stk;
            int u = 0;
            stk.push(0);
            bit.modify(L[0], 1);
            for(int i = 0; s[i]; i++) {
                if(s[i] == 'P') {
                    if(vis[u]) continue;
                    vis[u] = true;
    
                    for(int i = 0; i < vec[u].size(); i++) {
                        int x = t[vec[u][i].fi], id = vec[u][i].se;
                        ans[id] = bit.sum(R[x]) - bit.sum(L[x] - 1);
                    }
                } else if(s[i] == 'B') {
                    if(stk.size() > 1) {
                        bit.modify(L[u], -1);
                        stk.pop();
                        u = stk.top();
                    }
                } else {
                    int c = idx(s[i]);
                    u = ch[u][c];
                    stk.push(u);
                    bit.modify(L[u], 1);
                }
            }
            for(int i = 1; i <= n; i++) printf("%d
    ", ans[i]);
        }
    } ac(26);
    
    int main() {
        ac.init(); pos = 1;
        scanf("%s%d", s, &n);
        for(int i = 1; i <= n; i++) {
            scanf("%d%d", &qus[i].x, &qus[i].y);
            qus[i].id = i;
        }
        sort(qus + 1, qus + 1 + n);
        ac.addStr(s);
        ac.build();
        ac.solve(s);
        return 0;
    }
    
    
    /*
    */
  • 相关阅读:
    tuple 元组及字典dict
    day 49 css属性补充浮动 属性定位 抽屉作业
    day48 选择器(基本、层级 、属性) css属性
    day47 列表 表单 css初识
    day 46 http和html
    day 45索引
    day 44 练习题讲解 多表查询
    day 40 多表查询 子查询
    day39 表之间的关联关系、 补充 表操作总结 where 、group by、
    day38 数据类型 约束条件
  • 原文地址:https://www.cnblogs.com/CJLHY/p/9493530.html
Copyright © 2011-2022 走看看