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 ...
随机推荐
- 使用Quartz任务调用的时候报错Based on configured schedule, the given trigger will never fire.
org.quartz.SchedulerException: Based on configured schedule, the given trigger will never fire. 大概意思 ...
- 使用Foxfly.Net读取STEP文件
Foxfly.Net是具备基本的几何建模和CAD文件读取功能.本文主要介绍读取STP/STEP文件的使用方法. 1.初始化 项目中引入FoxflyNet.dll程序集,在Program.cs中初始化建 ...
- 关于IE的一些hack
TIPS:对于完全放弃IE的幸福开发者,以下内容全是废话,建议跳转到 博客园 着页,寻找更优质的文章. 对于前端开发来说IE一直是心里的痛,不管你觉得做的多好的网页,放到它上面总会有一些意想不到的问题 ...
- Vue汇总(搬砖)
掘金: https://juejin.im/ Element: http://element-cn.eleme.io/#/zh-CN 验证码GEETEST---极验 : https://docs.ge ...
- 使用Python开发环境Wing IDE设立项目注意事项
使用Wing IDE的第一步是建立一个项目文件,这样Wing IDE就可以找到并分析源代码,存储工作. Wing IDE会自动以默认的项目进行启动.在本教程中用户也可以使用这个默认项目进行示例操作.如 ...
- Piwik-2.16.1 (OpenLogic CentOS7.2)
平台: CentOS 类型: 虚拟机镜像 软件包: centos7.2 piwik devops log analysis monitoring open-source 服务优惠价: 按服务商许可协议 ...
- A011 Activiti工作流程开发的一些统一规则和实现原理(完整版)
注意:以下规则是我为了规范流程的处理过程,不是Activiti公司的官方规定. 1.流程启动需要设置启动者,在Demo程序中,“启动者变量”名统一设置为initUserId 启动时要做的: ident ...
- office密匙
office 2010 VYBBJ-TRJPB-QFQRF-QFT4D-H3GVB 6QFDX-PYH2G-PPYFD-C7RJM-BBKQ8 BDD3G-XM7FB-BD2HM-YK63V-VQFD ...
- MyDebugeer 一个简单调试器的实现
学习的是网上的帖子,所以就不贴源码了. 整个程序以调试循环为主体,实现了启动调试,继续执行,内存查看,读取寄存器值,显示源代码,断点的设置.查看.删除,三种单步执行:StepIn.StepOver.S ...
- leetcode--5 Longest Palindromic Substring
1. 题目: Given a string S, find the longest palindromic substring in S. You may assume that the maximu ...