震惊! AC自动机竟然这么简单

震惊! AC自动机竟然这么简单

Leetcode1032

基础概念

  1. 建立trie树, 同时需要有fail指针, 还有是否结束节点的标记

    1. 什么是fail指针

    从根节点到trie树上一个节点是一个字符串, 如果在此节点匹配失败, 需要找这个字符串的最长后缀, 能够被trie树接受, fail指针指向此时跳到的节点, 显然fail节点一定比当前节点高

    1. 结束节点的标记

    如果fail节点是结束节点, 那么当前节点也是结束节点

  2. 假儿子

    1. 若节点的某些儿子为空, 我们需要把它们转化为"假儿子", 即失配后跳到的某个节点

直接贴代码

class StreamChecker {
public:
    StreamChecker(vector& words) {
        root = new Node();
        for (int i = 0; i < words.size(); i++) {
            insert(words[i]);
        }
        build_succ();
        now = root;
    }
    bool query(char letter) {
        now = now->succ[letter - 'a'];
        return now->end;
    }
private:
    struct Node {
        Node* succ[26];
        Node* fail;
        bool end;
        Node() {
            memset(this, 0, sizeof(*this));
        }
    };
    Node* root;
    Node* now;
    void insert(const string& w) {
        Node* cur = root;
        for (int i = 0; i < w.size(); i++) {
            if (cur->succ[w[i] - 'a'] == NULL) {
                cur->succ[w[i] - 'a'] = new Node();
            }
            cur = cur->succ[w[i] - 'a'];
        }
        cur->end = true;
    }
    void build_succ() {
        root->fail = root;
        queue q;
        for (int i = 0; i < 26; i++) {
            if (root->succ[i] != NULL) {
                root->succ[i]->fail = root;
                q.push(root->succ[i]);
            } else {
                root->succ[i] = root;
            }
        }
        while (!q.empty()) {
            Node* cur = q.front();
            cur->end = cur->end || cur->fail->end;
            q.pop();
            for (int i = 0; i < 26; i++) {
                if (cur->succ[i] != NULL) {
                    cur->succ[i]->fail = cur->fail->succ[i];
                    q.push(cur->succ[i]);
                } else {
                    cur->succ[i] = cur->fail->succ[i];
                }
            }
        }
    }
};

/**
 * Your StreamChecker object will be instantiated and called as such:
 * StreamChecker* obj = new StreamChecker(words);
 * bool param_1 = obj->query(letter);
 */

你可能感兴趣的:(数据结构)