zoukankan      html  css  js  c++  java
  • 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
    ", ans[i]);
        }
        return 0;
    }
    
    /**
    **/
  • 相关阅读:
    DOM 获取元素,设置样式
    js检查浏览器内核版本信息
    获取浏览器可视屏幕宽度
    swift 闭包+嵌套函数+extension+单例+嵌套函数+??
    HTTP请求错误大全
    Swift:网络库Alamofire
    Swift 值类型和引用类型
    Swift URL Schemes使用
    Swift编程规范
    swift系统学习控件篇:UITableView+UICollectionView
  • 原文地址:https://www.cnblogs.com/CJLHY/p/11674400.html
Copyright © 2011-2022 走看看