zoukankan      html  css  js  c++  java
  • HDU 2222 Keywords Search(AC自动机模板题)

    学习AC自动机请戳这里:大神blog........

    自动机的模板:

    #include <iostream>
    #include <algorithm>
    #include <cmath>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <string>
    #include <vector>
    #include <set>
    #include <queue>
    #include <stack>
    #include <climits>//形如INT_MAX一类的
    #define MAX 100005
    #define INF 0x7FFFFFFF
    #define REP(i,s,t) for(int i=(s);i<=(t);++i)
    #define ll long long
    #define mem(a,b) memset(a,b,sizeof(a))
    #define mp(a,b) make_pair(a,b)
    #define L(x) x<<1
    #define R(x) x<<1|1
    # define eps 1e-5
    //#pragma comment(linker, "/STACK:36777216") ///传说中的外挂
    using namespace std;
    
    struct trie {
        trie *fail; //失败指针
        trie *next[26];
        int cnt;
        trie () {
            fail = 0;cnt = 0;
            memset(next,0,sizeof(next));
        }
    }*q[511111]; //模拟队列
    trie *rt;
    int head,tail;
    char keyword[51];
    char book[1111111];
    
    void insert(char *key) {
        trie *p = rt;
        int t;
        while(*key) {
            t = *key - 'a';
            if(p->next[t] == NULL) p->next[t] = new trie();
            p = p->next[t];
            key++;
        }
         p->cnt++; //表示一个单词
    }
    
    void bfs() {
        rt->fail = NULL; //根结点fail指向空
        q[head++] = rt;
        while(head != tail) {
            trie *t = q[tail++];
            trie *p = NULL;
            for(int i=0; i<26; i++) {
                if(t->next[i] != NULL) {                //对所有儿子的fail指针匹配并且入队
                    if(t == rt) t ->next[i]->fail = rt; //如果刚从根节点出发
                    else {                              //否则沿着他父亲的失败指针走,
                        //直到走到一个节点,他的儿子中也有相同字符的节点。然后把当前节点的失败指针指向他的那个儿子
                        p = t->fail;
                        while(p != NULL) {
                            if(p->next[i] != NULL) {
                                t->next[i]->fail = p->next[i];
                                break;
                            }
                            p = p->fail;
                        }
                        if(p == NULL) t->next[i]->fail = rt; //如果一直走到了root都没找到,那就把失败指针指向root
                    }
                    q[head++] = t->next[i];
                }
            }
        }
    }
    
    int query(char *key) {
        trie *p = rt;
        int cnt = 0;
        while(*key) {
            int t = *key - 'a';
            while(p->next[t] == NULL && p != rt) p = p->fail; //如果当前字符不匹配
            p = p->next[t];
            if(p == NULL) p = rt; //最终还是未匹配
            trie *tmp = p;
            while(tmp != rt && tmp->cnt != -1) {
                cnt += tmp->cnt;
                tmp->cnt = -1;    //该处已经出现过了
                tmp = tmp->fail;
            }
            key++;
        }
        return cnt;
    }
    int main(){
        int T;
        cin >> T;
        while(T --) {
            rt = new trie();
            int n;
            cin >> n;
            for(int i=0; i<n; i++) {
                scanf("%s",keyword);
                insert(keyword);
            }
            head = 0; tail = 0;
            bfs();
            scanf("%s",book);
            printf("%d
    ",query(book));
        }
        return 0;
    }
    


  • 相关阅读:
    转:高层游戏引擎——基于OGRE所实现的高层游戏引擎框架
    转: Orz是一个基于Ogre思想的游戏开发架构
    转:Ogre源代码浅析——脚本及其解析(一)
    IntelliJ IDEA添加过滤文件或目录
    为什么要使用ConcurrentHashMap
    volatile关键字解析
    Spring Boot MyBatis 通用Mapper 自动生成代码
    使用mysql乐观锁解决并发问题
    使用Redis分布式锁处理并发,解决超卖问题
    浅析 pagehelper 分页
  • 原文地址:https://www.cnblogs.com/riskyer/p/3228500.html
Copyright © 2011-2022 走看看