HDU:2222-Keywords Search(AC自动机模板,匹配模拟)
Keywords Search
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 131072/131072 K (Java/Others)
Problem Description
In the modern time, Search engine came into the life of everybody like Google, Baidu, etc.
Wiskey also wants to bring this feature to his image retrieval system.
Every image have a long description, when users type some keywords to find the image, the system will match the keywords with description of image and show the image which the most keywords be matched.
To simplify the problem, giving you a description of image, and some keywords, you should tell me how many keywords will be match.
Input
First line will contain one integer means how many cases will follow by.
Each case will contain two integers N means the number of keywords and N keywords follow. (N <= 10000)
Each keyword will only contains characters ‘a’-‘z’, and the length will be not longer than 50.
The last line is the description, and the length will be not longer than 1000000.
Output
Print how many keywords are contained in the description.
Sample Input
1
5
she
he
say
shr
her
yasherhs
Sample Output
3
解题心得:
- 首先就这个题来说只是AC自动机的一个模板题,今天刚把AC自动机学了,其实AC自动机并不是想象中的那么难,其实把两个前置技能字典树和KMP算法搞懂之后AC自动机也差不多水到渠成了。
- AC自动机也是字符串匹配,和KMP相比AC自动机处理的是多次匹配,如果使用KMP处理肯定会超时,而字典树是用来处理字符串的前缀的问题的,如果字符串过长,为了处理字符串中间的匹配,枚举字符串的每一个后缀来建树然后跑字典树肯定也会超时,这样结合字典树和KMP的AC自动机就出来了,既可以多次匹配还可以处理在字符串中间的匹配问题。
- 裸的AC自动机包含三个部分:
- 第一个部分就是字典树建树,AC自动机还是在字典树上跑的,只不过在建树的时候要注意一下,一个串结束时最后一个字符在树上的位置需要记录一下,这个不懂的先去看字典树。
- 第二个部分就是fail跳转,这个fail跳转其实就是参考的KMP的跳转思想,fail还是很形象的,失败之后就跳转,只不过KMP只是在一个线性表上面跳转,而fail跳转是在字典树上面跳转,在学fail跳转的时候要知道子节点的fail跳转位置都是通过父节点找到的,父节点寻找失败的时候就跳转父节点的fail,一直找不到跑到到根节点上,所以在写fail跳转的时候一定要弄清楚当前节点和父节点。
- 第三个就是询问,在寻找失败的时候要fail跳转,一直到找到第一个符合当前字符匹配的位置,找到的答案要标记,不然可能被重复找,但是上面说的是找到第一个符合匹配的位置,所以在找到之后还要继续跟着这个符合匹配的位置跳转,直到将树上所有的符合匹配的节点找完。
- 个人感觉这个fail标记像是在字符串去和字典树匹配,先从根节点开始往下面走,当在树上走不动的时候就往回走尝试从树的其他节点走,而fail其实就是标记的一个个你走不动的时候可以换路时,然后走另一条路,走不动就换,直到在根节点不能走了,那么就再从字符串的下一个字节再匹配,匹配成功的之后再将其他可以匹配的点也跳转过去。
#include<stdio.h>
#include<algorithm>
#include<queue>
#include<string.h>
using namespace std;
const int maxn = 1e6+100;
char s[maxn];
struct node
{
node *child[26];
node *fail;
int cnt;
node()//初始化每个节点
{
for(int i=0;i<26;i++)
child[i] = NULL;
fail = NULL;
cnt = 0;
}
};
node *root,*newnode,*current;
void insert_trie()//先建一颗字典树
{
int len = strlen(s),k;
current = root;
for(int i=0;i<len;i++)
{
int k = s[i] - 'a';
if(current->child[k] == NULL)
{
newnode = new node;
current->child[k] = newnode;
}
current = current->child[k];
}
current->cnt++;//记录以当前节点为字符串终点的数量
}
node *get_fail(node *p,int num)
{
if(p->child[num] != NULL)
return p->child[num];
else if(p == root)
return root;
else
return get_fail(p->fail,num);
}
void build_AC_automation()//建立fail跳转
{
current = root;
queue <node *> qu;//按照bfs搜索
qu.push(current);
while(!qu.empty())
{
current = qu.front();
qu.pop();
for(int i=0;i<26;i++)
{
if(current->child[i] != NULL)//如果当前的一个子节点不是空的那么就去找这个子节点匹配fail之后父节点跳转的位置
{
qu.push(current->child[i]);
if(current == root)//如果这个节点是根节点,那么子节点也只能往根节点上面跳了,没有其他办法了
current->child[i]->fail = root;
else
current->child[i]->fail = get_fail(current->fail,i);//子节点匹配fail失败之后跳转的位置是从父节点中找到的
}
}
}
}
void query()
{
int len = strlen(s),k,ans = 0;;
current = root;
for(int i=0;i<len;i++)
{
int k = s[i] - 'a';
//这一大坨都是为了找到第一可以匹配这个字符的位置
while(current->child[k] == NULL && current != root)//匹配失败是空的节点就往父节点fail跳转,找不到就会跳到根节点上面去
current = current->fail;
current = (current->child[k] == NULL)?root:current->child[k];//如果上面就已经跳到根节点就啥也不说了,不然就转移到这个可以转移的节点
node *temp = current;
//为何要写while循环,因为可能会有多个符合这个匹配的情况快要将树中符合情况的全给匹配完,这样才不会找漏
while(temp != root)//如果找到符合条件的节点就加上答案,然后标记这个已经找过的节点,然后就往其他符合的节点跳,找到的是已经被标记过的节点就直接跳出
{
if(temp->cnt >= 0)
{
ans += temp->cnt;
temp->cnt = -1;
}
else
break;
temp = temp->fail;
}
}
printf("%d\n",ans);
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
root = new node;
root->fail = root;
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%s",s);
insert_trie();
}
build_AC_automation();
scanf("%s",s);
query();
}
}
HDU:2222-Keywords Search(AC自动机模板,匹配模拟)的更多相关文章
- hdu 2222 Keywords Search ac自动机模板
题目链接 先整理一发ac自动机模板.. #include <iostream> #include <vector> #include <cstdio> #inclu ...
- HDU 2222 Keywords Search(AC自动机模板题)
学习AC自动机请戳这里:大神blog........ 自动机的模板: #include <iostream> #include <algorithm> #include < ...
- HDU 2222 Keywords Search (AC自动机)(模板题)
<题目链接> 题目大意: 给你一些单词,和一个字符串,问你这个字符串中含有多少个上面的单词. 解题分析: 这是多模匹配问题,如果用KMP的话,对每一个单词,都跑一遍KMP,那么当单词数量非 ...
- hdu 2222 Keywords Search——AC自动机
题目:http://acm.hdu.edu.cn/showproblem.php?pid=2222 第一道AC自动机! T了无数边后终于知道原来它是把若干询问串建一个自动机,把模式串放在上面跑:而且只 ...
- hdu 2222 Keywords Search ac自动机入门
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2222 题意:有N(N <= 10000)个长度不超过50的模式串和一个长度不超过1e6的文本串. ...
- HDU 2222 Keywords Search (AC自动机)
题意:就是求目标串中出现了几个模式串. 思路:用int型的end数组记录出现,AC自动机即可. #include<iostream> #include<cstdio> #inc ...
- Match:Keywords Search(AC自动机模板)(HDU 2222)
多模匹配 题目大意:给定很多个字串A,B,C,D,E....,然后再给你目标串str字串,看目标串中出现多少个给定的字串. 经典AC自动机模板题,不多说. #include <iostream& ...
- Keywords Search(AC自动机模板)
Keywords Search Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others ...
- POJ2222 Keywords Search AC自动机模板
http://acm.hdu.edu.cn/showproblem.php?pid=2222 题意:给出一些单词,求多少个单词在字符串中出现过(单词表单词可能有相同的,这些相同的单词视为不同的分别计数 ...
- hdu 2222 Keywords Search - Aho-Corasick自动机
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submissio ...
随机推荐
- Maven的学习资料收集--(十)Myeclipse下创建Maven的Web项目
先要在MyEclipse中对Maven进行设置: 到此Maven对MyEclipse的支持设置完毕. 下面我们在MyEclipse中创建一个Maven标准的Web工程: New --> We ...
- Maven的学习资料收集--(二)安装m2eclipse插件
在Eclipse中可以安装Maven插件,可以更方便的使用: 官网地址:http://www.eclipse.org/m2e/ 可以在线安装或者离线下载,之前在线安装总是失败,可能是网速的原因,找到了 ...
- Toad for Oracle针对于Oracle数据库的可视化管理工具使用
Toad for Oracle安装包下载地址:http://pan.baidu.com/s/1mgBOLZU 在Oracle应用程序的开发过程中,访问数据库对象和编写SQL程序是一件乏味且耗费时间的工 ...
- wcf_消息通信模式(下) 双工通讯
原文:[老老实实学WCF] 第十篇 消息通信模式(下) 双工 第十篇 消息通信模式(下) 双工 在前一篇的学习中,我们了解了单向和请求/应答这两种消息通信模式.我们知道可以通过配置操作协定的IsOne ...
- 封装一个帮助类来写文件到android外置存储器上
项目地址:点击打开 项目简介:写文件到android外置存储器的一个帮助类,和它的demo程序 它是如何工作的呢? 1.创建 AppExternalFileWriter 对象并传递context(上下 ...
- javascript数组属性及方法
数组元素的添加 1. arrayt.splice(index,howmany,item1,.....,itemX) 向/从数组中添加/删除项目,然后返回被删除的项目 2. array.unshift( ...
- https验证新发现-老知识
HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier); 可以设置https全局的域名校验规则 HttpsURLConnecti ...
- DDL与DML语句
1. DDL语句 SQL语句:结构化查询语句,使用SQL与数据库“沟通”,完成相应的数据库操作. l DDL:数据定义语言,用来维护数据库对象 1.1 创建表 Ø CREATE:创建表 演示:创建员工 ...
- [Rails学习之路]Rails路由配置
如果是使用Rails的默认约定,那么几乎是零配置. 但有些时候,我们可能不得不(或者更喜欢)进行一些特殊的配置. 其实Rails在路由功能中也有很丰富的配置选项. routes.rb文件中靠前的规则优 ...
- constraint的一些用法总结
主要就是增加约束的 以下几种约束 .并 一一列举: 1.主键约束: 要对一个列加主键约束的话,这列就必须要满足的条件就是分空 因为主键约束:就是对一个列进行了约束,约束为(非空.不重复) 以下是代码 ...