题目大意:给出一篇文章,长度最多1000000,若干个关键词,关键词有可能重复。关键词不超过10000,每个关键词不超过50个字符。请问该文章包含多少个关键词。

这是AC自动机的入门题。首先将关键词分别插入到一棵trie树中,对每个关键词的对应的结束节点设置一个标记;第二步设置trie树中节点的fail指针。每个节点u都得有fail指针,指向某一个节点v,表示当u无法继续往下匹配时,u应该跳转的节点。节点u与v的字符相同,且根到v的字符串为根到u的字符串的最长后缀。如果u没有找到对应的v,则u的fail指针指向root。root的fail指针指向自身;第三步则是查询。查询时从根节点开始。每次根据当前的字符在当前节点的儿子中找到对应节点,如果没有找到,则跳转到当前节点的fail指针处,一直要找到某个节点,在它儿子中存在和当前字符匹配的节点,然后继续往下。当然如果到了根节点也没有找到,则查找下一个字符了。这里要注意的是,即使当前节点可以继续往下匹配,在当前节点往下匹配之前,我们需要另外拿一个指针,从当前节点出发,通过fail指针往上遍历,筛选是否有结束节点。因为有些关键词可能是当前节点到根的字符串的后缀。每个节点被筛选后可以做一个标记,下次筛选到这里时可以提前退出了。这样可以保证每个节点最多被筛选一次。

具体见代码:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define MAXC 26
struct node
{
int cnt,fail,nxt[MAXC];
}trie[];
int root,tot=,myq[],res=,T,n,head,tail;
char artical[],word[];
void insert(int r,char *s)
{
int len=strlen(s),val;
for(int i=;i<len;i++)
{
val=s[i]-'a';
if(trie[r].nxt[val]==)
trie[r].nxt[val]=++tot;
r=trie[r].nxt[val];
}
trie[r].cnt++;
}
void build(int r)
{
trie[r].fail=r;
myq[tail++]=r;
while(head<tail)
{
r=myq[head++];
for(int i=;i<MAXC;i++)
{
int ch,p;
if(ch=trie[r].nxt[i])
{
myq[tail++]=ch;
for(p=trie[r].fail;p!=root&&trie[p].nxt[i]==;p=trie[p].fail);
int tmp=trie[p].nxt[i];//tmp可能为空,因为p可能为根节点。
if(tmp&&tmp!=ch)trie[ch].fail=tmp;//防止ch的fail指针指向自己
else trie[ch].fail=root;
}
}
}
}
void query(int r,char *s)
{
int len=strlen(s),val;
for(int i=;i<len;i++)
{
val=s[i]-'a';
while(r!=root&&trie[r].nxt[val]==)
r=trie[r].fail;
r=trie[r].nxt[val];
if(r==)r=root;
for(int temp=r;temp!=root;temp=trie[temp].fail)//查询时要另一个指针从当前节点通过fail往上找。
{
if(trie[temp].cnt==-)break; //凡是找过的节点cnt设置为-1.所以遇到,可以提前退出。
res+=trie[temp].cnt;
trie[temp].cnt=-;
}
}
}
int main()
{
scanf("%d",&T);
while(T--)
{
root=;
head=tail=;
tot=;
res=;
memset(trie,,sizeof trie);
scanf("%d",&n);
for(int i=;i<n;i++)
{scanf("%s",word);
insert(root,word);
}
scanf("%s",artical);
build(root);
query(root,artical);
printf("%d\n",res);
}
return ;
}

HDU 2222 关键词查找的更多相关文章

  1. HDU 2222  AC自动机模板题

    1.HDU 2222 2.题意:给出n个单词,一个字串,求有多少个单词在字串里出现了.注意给出的单词可能会重复,重复的不计. 3.总结:入门题.在查询这里还是不太懂. #include<bits ...

  2. HDU 2222 Keywords Search(AC自动机模版题)

    Keywords Search Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others ...

  3. HDU 2222 Keywords Search(查询关键字)

    HDU 2222 Keywords Search(查询关键字) Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K ...

  4. VC模拟发送数据包-百度关键词查找

    VC模拟发送数据包-百度关键词查找 逗比汪星人2009-09-06上传   VC模拟发送数据包-百度关键词abcdef查找 详情 http://blog.csdn.net/wangningyu htt ...

  5. HDU 2222 最简单的AC自动机套模板应用

    HDU 2222 题意:给出N(N<=10,000)个单词,每个单词长度不超过50.再给出一个字符串S,字符串长度不超过1,000,000.问有多少个单词出现在了字符串S中.(单词可能重复,单词 ...

  6. HDU 2222 (AC自动机)

    HDU 2222 Keywords search Problem : 给若干个模式串,询问目标串中出现了多少个模式串. Solution : 复习了一下AC自动机.需要注意AC自动机中的fail,和n ...

  7. HDU - 2222,HDU - 2896,HDU - 3065,ZOJ - 3430 AC自动机求文本串和模式串信息(模板题)

    最近正在学AC自动机,按照惯例需要刷一套kuangbin的AC自动机专题巩固 在网上看过很多模板,感觉kuangbin大神的模板最为简洁,于是就选择了用kuangbin大神的模板. AC自动机其实就是 ...

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

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

  9. hdu 2222 Keywords Search

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=2222 思路:裸AC自动机,直接贴代码做模板 #include<stdio.h> #includ ...

随机推荐

  1. jQuery $.each用法[转]

    jQuery $.each用法 以下内容非原创,来自百度文库http://wenku.baidu.com/view/4796b6145f0e7cd18425368e.html 通过它,你可以遍历对象. ...

  2. java并发编程学习笔记(一)初识并发原子性

    1.并发的意义 现在是一个多核的时代,并发的存在意义就是为了能够充分利用多核计算机的优势,提高程序的运行效率: 2.并发的风险 竞争-----多个线程对内存数据数据进行读写操作时,对数据处理结果的一个 ...

  3. 佛祖保佑,永无bug

    /* _ooOoo_ o8888888o 88" . "88 (| -_- |) O\ = /O ____/`---'\____ .' \\| |// `. / \\||| : | ...

  4. phonegap android 开发环境搭建

    1.下载JDK并安装   http://www.oracle.com/technetwork/java/javase/downloads/index-jsp-138363.html 配置环境变量   ...

  5. 关于几种编程过程中的注释(TODO、FIXME、XXX等)

    最近看别人写的代码,注意到很多规范的代码的注释写的都特别好.只是不太明白TODO.FIXME这些事什么意思.查阅资料,看到一篇博客,遂转载而来,以供今后查阅. (转载地址http://www.cnbl ...

  6. GTC China 2016观感

    上周二在北京参加了GTC China 2016,最大的感受就是一个字,“冷”!黄教主一如既往坚持机车皮夹克装,9月中旬的北京还没有那么的冷啊,感觉全场的空调简直是为他而开...好的,以上吐槽完毕,接着 ...

  7. @html.ActionLink的几种参数格式

    一 Html.ActionLink("linkText","actionName") 该重载的第一个参数是该链接要显示的文字,第二个参数是对应的控制器的方法, ...

  8. Android 学习第15课,Android 开发的单元测试、及输出错误信息

    这一节没有做实例,单元测试,以后用到再写吧

  9. Mongoose学习笔记

    #名词解释: Schema 一种以文件形式存储的数据库模型骨架,不具备对数据库操作的能力 Model 由Schema生成的模型,具有抽象属性和行为,能够操作数据库 Entity 由Model创建的实体 ...

  10. telnet -测试端口号

    点击计算机的开始菜单-->运行 ,输入CMD命令,然后确定.打开cmd命令行.   输入telnet测试端口命令: telnet IP 端口 或者 telnet 域名 端口 回车   如果端口关 ...