zoukankan      html  css  js  c++  java
  • HDU4787 GRE Words Revenge【AC自动机 分块】

    HDU4787 GRE Words Revenge

    题意:

    (N)次操作,每次记录一个(01)串或者查询一个(01)串能匹配多少个记录的串,强制在线

    题解:

    在线的AC自动机,利用分块来降低复杂度,建两个AC自动机,一个大的一个小的,每次往小的里面加字符串,当小的自动机的大小大于一定值之后把小的自动机和大的自动机合并,然后清空小的自动机
    每次询问把小的自动机和大的自动机的答案加在一起即可

    TIPS:不能把(fail)边直接作为子节点来建图,因为之后还要加字符串进去

    //#pragma GCC optimize("O3")
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<bits/stdc++.h>
    using namespace std;
    function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
    const int MAXN = 5e6+7;
    class ACautomaton{
    private:
        int fail[MAXN],ch[MAXN][2],tot,last[MAXN],cnt[MAXN];
        queue<int> que;
        bool updated;
        void buildfail(){
            for(int i = 0; i < 2; i++){
                if(!ch[0][i]) continue;
                que.push(ch[0][i]);
                fail[ch[0][i]] = last[ch[0][i]] = 0;
            }
            while(!que.empty()){
                int u = que.front();
                que.pop();
                for(int c = 0; c < 2; c++){
                    int v = ch[u][c];
                    if(!v) continue;
                    int p = fail[u];
                    while(p and !ch[p][c]) p = fail[p];
                    fail[v] = ch[p][c];
                    last[v] = cnt[fail[v]]?fail[v]:last[fail[v]];
                    que.push(v);
                }
            }
        }
    public:
        void clear(){
            for(int i = 0; i <= tot; i++){
                ch[i][0] = ch[i][1] = 0;
                cnt[i] = 0;
            }
            tot = 0; updated = false;
        }
        void insert(char *s){
            updated = true;
            int now = 0;
            for(int i = 0; s[i]; i++){
                int c = s[i] - '0';
                if(!ch[now][c]) ch[now][c] = ++tot;
                now = ch[now][c];
            }
            cnt[now] = 1;
        }
        int mt(int u){
            int ret = 0;
            while(u){
                ret += cnt[u];
                u = last[u];
            }
            return ret;
        }
        int match(char *s){
            if(updated) buildfail();
            updated = false;
            int ret = 0, now = 0;
            for(int i = 0; s[i]; i++){
                int c = s[i] - '0';
                while(now and !ch[now][c]) now = fail[now];
                now = ch[now][c];
                ret += mt(now);
            }
            return ret;
        }
        int size(){ return tot; }
        void merge(ACautomaton &rhs, int u, int v){
            updated = true;
            for(int c = 0; c < 2; c++){
                if(!rhs.ch[v][c]) continue;
                if(!ch[u][c]) ch[u][c] = ++tot;
                merge(rhs,ch[u][c],rhs.ch[v][c]);
            }
            cnt[u] |= rhs.cnt[v];
        }
    }aho[2];
    char s[MAXN],t[MAXN];
    void solve(int kase){
        printf("Case #%d:
    ",kase);
        aho[0].clear(); aho[1].clear();
        int lastres = 0, q;
        scanf("%d",&q);
        int up = sqrt(MAXN);
        while(q--){
            scanf("%s",s);
            int len = strlen(s+1);
            int shift = lastres % len;
            t[len] = '';
            for(int i = 0; i < len; i++) t[i] = s[(i+shift)%len+1];
            if(s[0]=='?') printf("%d
    ",lastres=aho[0].match(t)+aho[1].match(t));
            else{
                aho[1].insert(t);
                if(aho[1].size()>up){
                    aho[0].merge(aho[1],0,0);
                    aho[1].clear();
                }
            }
        }
    }
    int main(){
        int T; scanf("%d",&T);
        for(int kase = 1; kase <= T; kase++) solve(kase);
        return 0;
    }
    
  • 相关阅读:
    A Plug for UNIX (最大流 邻接矩阵dinic)POJ
    Dining POJ
    ACM Computer Factory (邻接矩阵 dinic 模板)(最大流+路径输出)POJ
    HDU
    E
    2018 东北赛i 简单dpI
    Coloring Brackets CodeForces
    2019浙江省赛j welcome Party
    D
    Critical Links (UVA
  • 原文地址:https://www.cnblogs.com/kikokiko/p/12883857.html
Copyright © 2011-2022 走看看