题目大意:给出一篇文章,长度最多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. nodejs授权连接mongodb

    mongodb安装完以后是没有用户连接授权验证的 在控制台直接输入mongo进入交互模式 show dbs use databaseName show collections 这些基本的命令都不会有问 ...

  2. [转载]HDU 3478 判断奇环

    题意:给定n个点,m条边的无向图(没有重边和子环).从给定点出发,每个时间走到相邻的点,可以走重复的边,相邻时间不能停留在同一点,判断是否存在某个时间停留在任意的n个点. 分析: (1)首先,和出发点 ...

  3. Telnet

    http://blog.sina.com.cn/s/blog_607072980102uy06.html

  4. bootstrap总结

    bootstrap在reset.css文件中设置margin为0,因此其他的标签需要重新设计margin. 1.h <h>标签和普通使用方法一样. 定义了.h1~.h6六个类名,样式和标题 ...

  5. foreach为什么要实现IEnumerable接口而不是直接用IEnumerator接口

    在.Net中,要想被foreach遍历,那么目标对象要实现IEnumerable或IEnumerable<T>接口,这个接口有一个方法,GetEnumerator(),返回一个IEnume ...

  6. Koala-Sass编译

    1.安装: 下载地址:http://koala-app.com/ 安装好了之后,打开界面如下: 2.简单配置: 打开设置: 3.设置中文: 打开安装目录下的文件:C:\Program Files (x ...

  7. Techparty-广州 10 月 31 日 Docker 专场沙龙 后记

    华为的童鞋技术能力很强,但是两位讲师的都没听进去.重点听了两个,一个是芒果TV的Docker 之路,另一个是Coding的实践和思考. 芒果TV的主讲人是一直仰慕的CMGS,从豆瓣出来后去了国企芒果台 ...

  8. Gradle简介和安装

    一.Gradle介绍 Gradle是一个基于JVM的构建工具,它提供了:像Ant一样,通用灵活的构建工具,可以切换的,基于约定的构建框架,强大的多工程构建支持,基于Apache Ivy的强大的依赖管理 ...

  9. 判断App运行是否在前台

    转自:http://notes.stay4it.com/2016/02/26/check-if-app-is-running-forground/ 在一些场景中,经常会需要判断App是否在后台运行,比 ...

  10. [读书笔记]Java之静态分派

    以下内容来自周志明的<深入理解Java虚拟机>. 静态分派和重载有关. 先看代码: public static void main(String[] args) { SuperClass ...