• HDU 2222 AC自动机


    题目链接http://acm.hdu.edu.cn/showproblem.php?pid=2222.

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <cctype>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <map>
    #include <algorithm>
    #include <iostream>
    #include <string>
    #include <set>
    #define X first
    #define Y second
    #define sqr(x) (x)*(x)
    #pragma comment(linker,"/STACK:102400000,102400000")
    using namespace std;
    const double PI = acos(-1.0);
    map<int, int>::iterator it;
    typedef long long LL ;
    template<typename T> void checkmin(T &x, T y) {x = min(x, y);}
    template<typename T> void checkmax(T &x, T y) {x = max(x, y);}
    
    //MAX_NODE = StringNumber * StringLength
    const int MAX_NODE = 500000 + 50;
    //节点个数,一般字符形式的题26个
    const int CHILD_NUM = 26;
    //特定题目需要
    const int mod = 20090717;
    
    class ACAutomaton {
        private:
            //每个节点的儿子,即当前节点的状态转移
            int chd[MAX_NODE][CHILD_NUM];
            //记录题目给的关键数据
            int val[MAX_NODE];
            //传说中的fail指针
            int fail[MAX_NODE];
            //队列,用于广度优先计算fail指针
            int Q[MAX_NODE];
            //字母对应的ID
            int ID[128];
            //已使用节点个数
            int sz;
        public:
            //初始化,计算字母对应的儿子ID,如:'a'->0 ... 'z'->25
            void Initialize() {
                fail[0] = 0;
                for(int i = 0 ; i < CHILD_NUM ; i ++) {
                    ID[i+'a'] = i;
                }
            }
            //重新建树需先Reset
            void Reset() {
                memset(chd[0] , -1 , sizeof(chd[0]));
                sz = 1;
            }
            //将权值为key的字符串a插入到trie中
            void Insert(char *a, int key) {
                int p = 0;
                for(; *a ; ++ a) {
                    int c = ID[*a];
                    if(chd[p][c] == -1) {
                        memset(chd[sz] , -1 , sizeof(chd[sz]));
                        val[sz] = 0;
                        chd[p][c] = sz ++;
                    }
                    p = chd[p][c];
                }
    
                val[p] += key;
            }
            //建立AC自动机,确定每个节点的权值以及状态转移
            void Construct() {
                int *s = Q , *e = Q;
                for(int i = 0 ; i < CHILD_NUM ; i ++) {
                    if(~chd[0][i]) {
                        fail[ chd[0][i] ] = 0;
                        *e ++ = chd[0][i];
                    }
                }
                while(s != e) {
                    int r = *s++;
                    for(int i = 0 ; i < CHILD_NUM ; i ++) {
                        int u = chd[r][i];
                        if(~u) {
                            *e ++ = u;
                            int v = fail[r];
                            while(chd[v][i] == -1 && v)v = fail[v];
    
                            fail[u] = chd[v][i] == -1 ? 0 : chd[v][i];
                        }
                    }
                }
            }
            //询问所给字符串包含多少个模式串
            int Query(char *s) {
                int q = 0;
                int ret = 0;
                for(; *s; ++s) {
                    int c = ID[*s];
                    while(chd[q][c] == -1 && q)q = fail[q];
                    q = chd[q][c];
                    if(q == -1)q = 0;
                    int p = q;
                    while(p) {
                        if(val[p]) {
                            ret += val[p];
                            val[p] = 0;
                        }
                        else {
                            break;
                        }
                        p = fail[p];
                    }
                }
                return ret;
            }
    } AC;
    
    char s[1000005], t[10005];
    int main() {
        int T;
        AC.Initialize();
        scanf("%d", &T);
        while(T--) {
            AC.Reset();
            int n;
            scanf("%d", &n);
            for(int i = 0; i < n; ++i) {
                scanf("%s", t);
                AC.Insert(t, 1);
            }
            AC.Construct();
            scanf("%s", s);
            int res = AC.Query(s);
            printf("%d
    ", res);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Educational Codeforces Round 67 D. Subarray Sorting
    2019 Multi-University Training Contest 5
    Educational Codeforces Round 69 (Rated for Div. 2) E. Culture Code
    Educational Codeforces Round 69 D. Yet Another Subarray Problem
    2019牛客暑期多校训练第六场
    Educational Codeforces Round 68 E. Count The Rectangles
    2019牛客多校第五场题解
    2019 Multi-University Training Contest 3
    2019 Multi-University Training Contest 2
    [模板] 三维偏序
  • 原文地址:https://www.cnblogs.com/cxw199204/p/3384409.html
Copyright © 2020-2023  润新知