Codeforces 1207G Indie Album AC自动机

Indie Album

我的写法是对询问串建ac自动机, 原来的串建trie图, 然后两边同时跑, 最后dsu on tree + bit 统计。。

其实可以不用这么麻烦, 我们把原串和询问串一起建一个ac自动机, 那么对一个一个串有贡献的在

fail树的子树里, 所以只要在trie图上dfs一下, bit维护一下个数就好了。

#include<bits/stdc++.h>
using namespace std;

const int N = (int)5e5 + 7;

int n, m;
int Rt = 1, ch[N][26], trie_cnt = 1;
int pos[N];
int ans[N];
char s[N];

vector<pair<int, int>> V[N], Q[N];
vector<int> G[N];

struct Bit {
    int a[N];
    inline void modify(int x, int v) {
        for(int i = x; i < N; i += i & -i) {
            a[i] += v;
        }
    }
    inline int sum(int x) {
        int ans = 0;
        for(int i = x; i; i -= i & -i) {
            ans += a[i];
        }
        return ans;
    }
} bit;

inline int ID(char c) {
    return c - 'a';
}

int in[N], ot[N], dfs_clock;

void dfs(int u) {
    in[u] = ++dfs_clock;
    for(int i = 0; i < 26; i++) {
        if(!ch[u][i]) continue;
        dfs(ch[u][i]);
    }
    ot[u] = dfs_clock;
}

struct Ac {
    // 1. init before use
    // 2. check character set
    // 3. use build
    int ch[N][26], f[N], tot, sz, subVal;
    inline int newNode() {
        tot++; f[tot] = 0;
        memset(ch[tot], 0, sizeof(ch[tot]));
        return tot;
    }
    void init(int _sz, int _subVal) {
        sz = _sz; subVal = _subVal;
        tot = -1; newNode();
    }
    inline int idx(int c) {return c - subVal;}
    int addStr(char* s) {
        int u = 0;
        for(int i = 0; s[i]; i++) {
            int c = idx(s[i]);
            if(!ch[u][c]) ch[u][c] = newNode();
            u = ch[u][c];
        }
        return 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();
            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 getGraph() {
        for(int i = 1; i <= tot; i++) {
            G[f[i]].push_back(i);
        }
    }
} ac;

void go(int u, int cur) {
    V[cur].push_back(make_pair(in[u], ot[u]));
    for(int i = 0; i < 26; i++) {
        if(!ch[u][i]) continue;
        go(ch[u][i], ac.ch[cur][i]);
    }
}

int son[N], sz[N];

void gao(int u) {
    son[u] = -1;
    sz[u] = 1;
    for(auto &v : G[u]) {
        gao(v);
        sz[u] += sz[v];
        if(son[u] == -1 || sz[v] > sz[son[u]]) {
            son[u] = v;
        }
    }
}

void flip(int u, int op) {
    for(auto &t : V[u]) {
        bit.modify(t.first, op);
        bit.modify(t.second + 1, -op);
    }
}

void modify(int u, int op) {
    flip(u, op);
    for(auto &v : G[u]) {
        modify(v, op);
    }
}

void solve(int u, bool keep) {
    for(auto &v : G[u]) {
        if(v == son[u]) continue;
        solve(v, false);
    }
    if(son[u]) solve(son[u], true);
    for(auto &v : G[u]) {
        if(v == son[u]) continue;
        modify(v, 1);
    }
    flip(u, 1);
    for(auto &q : Q[u]) {
        ans[q.second] = bit.sum(q.first);
    }
    if(!keep) {
        modify(u, -1);
    }
}

int main() {
    ac.init(26, 'a');
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) {
        int op; scanf("%d", &op);
        if(op == 1) {
            char c[4];
            scanf("%s", c);
            if(!ch[Rt][ID(*c)]) ch[Rt][ID(*c)] = ++trie_cnt;
            pos[i] = ch[Rt][ID(*c)];
        }
        else {
            int j; char c[4];
            scanf("%d%s", &j, c);
            int cur = pos[j];
            if(!ch[cur][ID(*c)]) ch[cur][ID(*c)] = ++trie_cnt;
            pos[i] = ch[cur][ID(*c)];
        }
    }
    dfs(Rt);
    scanf("%d", &m);
    for(int i = 1; i <= m; i++) {
        int x; scanf("%d", &x);
        scanf("%s", s);
        int p = ac.addStr(s);
        Q[p].push_back(make_pair(in[pos[x]], i));
    }
    ac.build();
    go(Rt, 0);
    ac.getGraph();
    gao(0);
    solve(0, false);
    for(int i = 1; i <= m; i++) {
        printf("%d\n", ans[i]);
    }
    return 0;
}

/**
**/

 

上一篇:Python实训Day03笔记:京东评论数据分析与可视化项目


下一篇:Android LitePal第三方库使用详解