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 ...
随机推荐
- Day1上
上午发挥强差人意.心态不好,编译器一直报错,心里比较慌. t1 每一个P枚举底数 .可二分 T2 暴力30 打标60 x^3-y^3=(x-y)*(x^2+xy+y^2). x-y==1. ! p ...
- [LeetCode]3. Longest Substring Without Repeating Characters无重复字符的最长子串
Given a string, find the length of the longest substring without repeating characters. Example 1: In ...
- JSPt的Base标签
<base href="${pageContext.request.contextPath}/"/> 注意:base标签得到的内容是: /projectName/ 这种 ...
- redis---安全设置
redis的安全性是通过设置口令来实现的. 首先打开redis的配置文件,我的是在/etc/redis/redis.conf,个人的路径可能会有不同,可以自行查找. 打开redis.conf文件以后, ...
- 在wpf或winform关闭子窗口或对子窗口进行某个操作后刷新父窗口
父窗口: ///<summary> ///弹出窗口 ///</summary> ///<param name="sender"></pa ...
- aar、jar、so的引入和aar打包包含so、aar、jar文件
so依赖 1,先建本地仓库,指向so放置的目录
- Cocos2d-x v3.1 核心类Director,Scene,Layer和Sprite(六)
Cocos2d-x v3.1 核心类Director,Scene,Layer和Sprite(六) Scene就像一个舞台一样在上面会摆放各种的元素,有的是固定的比如说布景,道具都是固定不动的,但有的元 ...
- 【extjs6学习笔记】1.12 初始: Working with DOM
http://www.extjs-tutorial.com/extjs/working-with-dom Ext JS是一个DHTML库. 它通过使用JavaScript创建或操作DOM元素来创建UI ...
- nginx 升级为最新版 nginx -1.12.0
标签:nginx 公司目前使用的nginx版本比较低(nginx-1.0.12),请网络安全公司做了一下“远程安全评估”,发现有下列漏洞: nginx URI处理安全限制绕过漏洞(CVE-2013-4 ...
- HDU 2602 Bone Collector骨头收藏者(01背包)
题意:收藏骨头. 思路: 常规的01背包. #include <iostream> #define N 1005 using namespace std; int volume[N]; / ...