HDU 2222 关键词查找
题目大意:给出一篇文章,长度最多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 关键词查找的更多相关文章
- HDU 2222 AC自动机模板题
1.HDU 2222 2.题意:给出n个单词,一个字串,求有多少个单词在字串里出现了.注意给出的单词可能会重复,重复的不计. 3.总结:入门题.在查询这里还是不太懂. #include<bits ...
- HDU 2222 Keywords Search(AC自动机模版题)
Keywords Search Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others ...
- HDU 2222 Keywords Search(查询关键字)
HDU 2222 Keywords Search(查询关键字) Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K ...
- VC模拟发送数据包-百度关键词查找
VC模拟发送数据包-百度关键词查找 逗比汪星人2009-09-06上传 VC模拟发送数据包-百度关键词abcdef查找 详情 http://blog.csdn.net/wangningyu htt ...
- HDU 2222 最简单的AC自动机套模板应用
HDU 2222 题意:给出N(N<=10,000)个单词,每个单词长度不超过50.再给出一个字符串S,字符串长度不超过1,000,000.问有多少个单词出现在了字符串S中.(单词可能重复,单词 ...
- HDU 2222 (AC自动机)
HDU 2222 Keywords search Problem : 给若干个模式串,询问目标串中出现了多少个模式串. Solution : 复习了一下AC自动机.需要注意AC自动机中的fail,和n ...
- HDU - 2222,HDU - 2896,HDU - 3065,ZOJ - 3430 AC自动机求文本串和模式串信息(模板题)
最近正在学AC自动机,按照惯例需要刷一套kuangbin的AC自动机专题巩固 在网上看过很多模板,感觉kuangbin大神的模板最为简洁,于是就选择了用kuangbin大神的模板. AC自动机其实就是 ...
- hdu 2222 Keywords Search ac自动机入门
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2222 题意:有N(N <= 10000)个长度不超过50的模式串和一个长度不超过1e6的文本串. ...
- hdu 2222 Keywords Search
链接:http://acm.hdu.edu.cn/showproblem.php?pid=2222 思路:裸AC自动机,直接贴代码做模板 #include<stdio.h> #includ ...
随机推荐
- loadRunner录制脚本常见问题及解决方法
1.是用IE9录制IE浏览器异常关闭 系统:win7 LR:11 浏览器:IE9 lr使用IE9录制脚本时,浏览器异常关闭且lr报the recording of the application wa ...
- c++unsigned char的输出问题
unsigned char的范围是0~255,在用cout输出的时候要显示数字的话记得进行int的强制转化才可以,否则都是输出的字符,除此之外的所有比较转换成整数在做比较吧 除此之外,在最近的项目里由 ...
- HDU2544 最短路dij
纯最短路. ///HDU 2544堆优化的最短路 #include <cstdio> #include <iostream> #include <sstream> ...
- CentOS下查看进程和删除进程
1. 在 LINUX 命令平台输入 1-2 个字符后按 Tab 键会自动补全后面的部分(前提是要有这个东西,例如在装了 tomcat 的前提下, 输入 tomcat 的 to 按 tab).2. ps ...
- HDU 5289
http://acm.hdu.edu.cn/showproblem.php?pid=5289 给一个数列,求有多少区间,使得这些区间内的最大值减最小值小于k 单调队列的功能:O(1) 插入,删除,最大 ...
- IOS懒加载
1.懒加载基本 懒加载——也称为延迟加载,即在需要的时候才加载(效率低,占用内存小).所谓懒加载,写的是其get方法. 注意:如果是懒加载的话则一定要注意先判断是否已经有了,如果没有那么再去进行实例化 ...
- 开始写Effective系列总结一些前端的心得
确实是没有时间整理以及总结和发表自己的感慨.难得中秋银行的事情搞完了自己清闲3天,是时候总结一下从大公司做.NET PC 端网站的开发到现在做移动互联网的银行及政府微信公众号的开发的感触.当时自己的选 ...
- const成员变量初始化总结
const可以用来声明常量也就是说他的值不能被修改: const成员必须在定义的时候同时初始化,不能进行赋值 如 const int a:a的值不能修改,不能给它赋值,如何才能让它一开始就拥有一个值? ...
- Git分支管理
一.Git分支的使用 查看分支: git branch 创建分支: git branch branch1 切换到branch1 git checkout branch1 再用git branch查看, ...
- CentOS7防火墙
一.CentOS7依然使用iptables的方法 CentOS7不再使用iptables,而是使用firewalld,若不想使用firewalld,可以停掉firewalld并且安装iptables- ...