题意:给你几个keywords,再给你一段文章,问你keywords出现了几次。

思路:这里就要用到多模匹配算法AC自动机了,AC自动机需要KMP和字典树的知识,匹配时是在字典树上,失配我们就要用到类似KMP的失配值了,如果失配,我们就沿着失配值到某个节点开始匹配,因为是多模匹配,我们每次失配移动都会从某一keyword的某部分开始匹配,这样就节省了很多时间。

话说第一次听到AC自动机我竟天真的以为是会自动AC题目的算法...orz

参考:

AC自动机算法详解 (转载)

ac自动机最详细的讲解,让你一次学会ac自动机。

AC自动机算法及模板

代码:

#include<cstdio>
#include<vector>
#include<stack>
#include<queue>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#define ll long long
const int maxn = 1000000+5;
const int maxm = 100000+5;
const int MOD = 1e7;
const int INF = 0x3f3f3f3f;
using namespace std;
struct Trie{
    Trie *next[26];
    Trie *fail; //失配值
    int sum;    //以此为单词结尾的个数
    Trie(){
        sum = 0;
        memset(next,NULL,sizeof(next));
        fail = NULL;
    }
};
Trie *root;
Trie *q[maxn];  //模拟队列
int head,tail;
void insert(char *s){
    Trie *p = root;
    for(int i = 0;s[i];i++){
        int x = s[i] - 'a';
        if(p ->next[x] == NULL){
            p ->next[x] = new Trie();
        }
        p = p ->next[x];
    }
    p ->sum++;
}
void buildFail(){   //计算失配值
    head = 0,tail = 1;
    q[head] = root;
    Trie *p,*temp;
    while(head < tail){
        temp = q[head++];
        for(int i = 0;i <= 25;i++){
            if(temp ->next[i]){
                if(temp == root){   //父节点为root,fail为root
                    temp ->next[i] ->fail = root;
                }
                else{
                    p = temp ->fail;    //查看父节点的fail
                    while(p){
                        if(p ->next[i]){
                            temp ->next[i] ->fail = p ->next[i];
                            break;
                        }
                        p = p ->fail;
                    }
                    if(p == NULL) temp ->next[i] ->fail = root;
                }
                q[tail++] = temp ->next[i];
            }
        }
    }
}
int ac_automation(char *ch){
    //p为模式串指针
    int cnt = 0;
    Trie *p = root;
    int len = strlen(ch);
    for(int i = 0;i < len;i++){
        int x = ch[i] - 'a';
        while(!p ->next[x] && p != root)
            p = p ->fail;
        p = p ->next[x];    //找到后p指针指向该结点
        if(!p) p = root;    //若指针返回为空,则没有找到与之匹配的字符
        Trie *temp = p;
        while(temp != root){
            if(temp ->sum >= 0){    //判断该结点是否被访问
                cnt += temp ->sum;
                temp ->sum = -1;
            }
            else break;
            temp = temp ->fail;
        }
    }
    return cnt;
}
char word[maxn];
int main(){
    int T,n;
    char s[55];
    scanf("%d",&T);
    while(T--){
        root = new Trie();
        scanf("%d",&n);
        for(int i = 0;i < n;i++){
            scanf("%s",s);
            insert(s);
        }
        scanf("%s",word);
        buildFail();
        int cnt = ac_automation(word);
        printf("%d\n",cnt);
    }
    return 0;
}

HDU 2222 Keywords Search(AC自动机)题解的更多相关文章

  1. hdu 2222 Keywords Search——AC自动机

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=2222 第一道AC自动机! T了无数边后终于知道原来它是把若干询问串建一个自动机,把模式串放在上面跑:而且只 ...

  2. hdu 2222 Keywords Search ac自动机入门

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2222 题意:有N(N <= 10000)个长度不超过50的模式串和一个长度不超过1e6的文本串. ...

  3. HDU 2222 Keywords Search(AC自动机模板题)

    学习AC自动机请戳这里:大神blog........ 自动机的模板: #include <iostream> #include <algorithm> #include < ...

  4. HDU 2222 Keywords Search (AC自动机)

    题意:就是求目标串中出现了几个模式串. 思路:用int型的end数组记录出现,AC自动机即可. #include<iostream> #include<cstdio> #inc ...

  5. hdu 2222 Keywords Search ac自动机模板

    题目链接 先整理一发ac自动机模板.. #include <iostream> #include <vector> #include <cstdio> #inclu ...

  6. HDU 2222 Keywords Search (AC自动机)(模板题)

    <题目链接> 题目大意: 给你一些单词,和一个字符串,问你这个字符串中含有多少个上面的单词. 解题分析: 这是多模匹配问题,如果用KMP的话,对每一个单词,都跑一遍KMP,那么当单词数量非 ...

  7. hdu 2222 Keywords Search - Aho-Corasick自动机

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submissio ...

  8. hdoj 2222 Keywords Search(AC自动机)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2222 思路分析:该问题为多模式匹配问题,使用AC自动机解决:需要注意的问题是如何统计该待查询的字符串包 ...

  9. hdu 2222 Keywords Search ac自己主动机

    点击打开链接题目链接 Keywords Search Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Ja ...

  10. HDU 2222 Keywords Search AC自己主动机入门题

    单词统计的题目,给出一些单词,统计有多少单词在一个文本中出现,最经典的入门题了. AC自己主动机的基础: 1 Trie. 以这个数据结构为基础的,只是添加一个fail指针和构造fail的函数 2 KM ...

随机推荐

  1. WEB安全第二篇--用文件搞定服务器:任意文件上传、文件包含与任意目录文件遍历

    零.前言 最近做专心web安全有一段时间了,但是目测后面的活会有些复杂,涉及到更多的中间件.底层安全.漏洞研究与安全建设等越来越复杂的东东,所以在这里想写一个系列关于web安全基础以及一些讨巧的pay ...

  2. Service简介 demos

    extends:http://blog.csdn.net/ithomer/article/details/7364024 一. Service简介 Service是android 系统中的四大组件之一 ...

  3. Unity3D之Unity3D 4.3.0 破解方法

    Dear  All 破解有风险,破解不尊重知识产权,如果有涉及请删除或者联系我……以下呢 是我这几天捣鼓的4.3.0版本 供学习!请大家支持正版! 1.下载最新版本 我是在Unity官网下载的最新版本 ...

  4. CentOS6.8系统安装Oracle11g

    1.官网上下载 软件安装包: linux.x64_11gR2_database_1of2.zip linux.x64_11gR2_database_2of2.zip 解压后: 生成文件夹: datab ...

  5. angular -- get请求该如何使用?

    在做 angualr 的开发过程中,经常会用到的就是 ajax 请求.下面是 get 请求示例: 如果存在多个 get 请求可以考虑进行封装下: // get 携参数访问 ajaxGet(getUrl ...

  6. 170804、使用Joda-Time优雅的处理日期时间

    简介 在Java中处理日期和时间是很常见的需求,基础的工具类就是我们熟悉的Date和Calendar,然而这些工具类的api使用并不是很方便和强大,于是就诞生了Joda-Time这个专门处理日期时间的 ...

  7. SaltStack实现Haproxy Nginx+php MySQL主从

    构建图如下 参考文档:https://github.com/unixhot/saltbook-code/tree/master

  8. 第二次作业(WordCount)

    1 Github项目地址:https://gitee.com/DamonGetup/WordCount/tree/master 2 对程序设计语言源文件统计字符数.单词数.行数,统计结果以指定格式输出 ...

  9. Python开发【模块】:Urllib(二)

    Urllib实战 1.爬取糗事百科中段子和用户名: 代码实例: # 爬取网站页面内容 import re import urllib.request url = 'https://www.qiushi ...

  10. mysql 数据操作 单表查询 group by 聚合函数 没有group by情况下

    聚合函数只能用在组里使用 #没有group by 则默认算作一组 取出所有员工的最高工资 mysql> select max(salary) from employee; +---------- ...