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 ...
随机推荐
- Elasticsearch在后台启动
Elasticsearch在linux下使用命令sh elasticsearch start,按键ctrl+c的时候程序就会stop掉,如何将程序在后台启动呢? 需要使用:./elasticsearc ...
- SpringBoot的优缺点
优点: 1.快速构建项目 2.对主流开发框架的无配置继承 3.项目可独立运行,无须外部依赖Servlet容器 4.提高运行时的应用监控 5.极大地提高了开发.部署效率 6.与云计算的天然集成 缺点: ...
- String.format()的用法
string.format()用法 2011-06-21 14:58:57| 分类: 工作笔记 | 标签:string format用法 |字号大中小 订阅 1.格式化货币(跟系统的环境有关 ...
- 创见VR-上海,会后总结
第一次,参加这种VR会,感觉不错.上午突然发现自己之前的一款AR Demo下载量在10-50了,真没想到,虽然这款Demo有一处bug至今未修复 ^^.不过,看来现在AR/VR确实恨火. ZSpace ...
- 大数四则运算java(转)
// 大数的四则运算 #include <iostream> #include <string> #include <algorithm> using namesp ...
- centos6.2安装内核
http://vault.centos.org/6.2/updates/Source/SPackages/ yum install rpm-build redhat-rpm-config unifde ...
- python logging 模块记录日志
#日志记录到多文件示例 import logging def error_log(message): file_1_1 = logging.FileHandler('error.log', 'a+', ...
- 【BZOJ1036】[ZJOI2008] 树的统计Count(一道可怕的模板题:树剖+线段树)
点此看题面 题解 这真的只是一道模板题:一个树链剖分套上一个线段树(令我窒息的组合). 既然是模板题,那就直接上代码吧. 代码 #include<bits/stdc++.h> #defin ...
- BZOJ 3873: [Ahoi2014]拼图
BZOJ 3873: [Ahoi2014]拼图 标签(空格分隔): OI-BZOJ OI-DP Time Limit: 10 Sec Memory Limit: 256 MB Description ...
- 如何更改VirtualBox虚拟电脑内存大小