AC 自动机

hdu 2222 题。。(这题号。。。)http://acm.hdu.edu.cn/showprob…

#include <iostream>
#include <stdio.h>
#include <memory.h>
#include <string>
#include <queue>

#define CHAR_COUNT 26

class Node {
public:
    Node() {
        memset(this, 0, sizeof(*this));
    }
    char ch;
    Node* fail;
    Node* next[CHAR_COUNT];
    int prefix;
};

class Trie {
public:
    Node* root;

    Trie() {
        root = new Node();
    }

    void insert(const char* str) {
        Node* p = this->root;
        for (int i = 0; str[i]; i++) {
            char ch = str[i]-'a';
            if (p->next[ch] == NULL) {
                p->next[ch] = new Node();
            }
            p = p->next[ch];
            p->ch = str[i];
        }
        p->prefix++;
    }

    void build() {
        std::queue<Node*> q;
        q.push(root);
        while ( ! q.empty()) {
            Node* tmp = q.front();
            q.pop();
            for (int i = 0; i < CHAR_COUNT; i++) {
                if (tmp->next[i]) {
                    if (tmp == root) {
                        tmp->next[i]->fail = root;
                    } else {
                        Node* p = tmp->fail;
                        while (p) {
                            if (p->next[i]) {
                                tmp->next[i]->fail = p->next[i];
                                break;
                            }
                            p = p->fail;
                        }
                        if ( ! p) {
                            tmp->next[i]->fail = root;
                        }
                    }
                    q.push(tmp->next[i]);
                }
            }
        }
    }

    int query(const char* str) {
        int ret = 0;
        Node* p = root;
        for (int i = 0; str[i]; i++) {
            char ch = str[i]-'a';
            while ( ! p->next[ch] && p != root) {
                p = p->fail;
            }
            p = p->next[ch];
            if ( ! p) {
                p = root;
            }
            Node* tmp = p;
            while (tmp != root && tmp->prefix != -1) {
                ret += tmp->prefix;
                tmp->prefix = -1;
                tmp = tmp->fail;
            }
        }
        return ret;
    }
};


int main() {
    int t;
    scanf("%d", &t);
    while (t--) {
        Trie trie;
        int n;
        scanf("%d", &n);
        while (n--) {
            std::string keyword;
            std::cin>>keyword;
            trie.insert(keyword.c_str());
        }
        trie.build();
        std::string query;
        std::cin>>query;
        printf("%d\n", trie.query(query.c_str()));
    }
    return 0;
}

这个实现是面向对象版本的,说明在这里,http://www.cppblog.com/mythit/…http://mindlee.net/2011/11/25/…http://blog.csdn.net/shuangde8…

One thought on “AC 自动机

  1. 注意到上面有一个 prefix 这个变量,实际上,是因为题目中,给出的关键词可能有重复的,而对于有重复的关键词,需要计数两次,所以才需要这个东西

Leave a Reply

Your email address will not be published. Required fields are marked *