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\n", 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;
}


/*
*/

 

posted @ 2018-08-17 15:28  NotNight  阅读(210)  评论(0编辑  收藏  举报