Time Limit: 1000MS   Memory Limit: 131072KB   64bit IO Format: %I64d & %I64u

Submit Status

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
 ——————————————————————————————————————————————————————————————————————————————————
题目大意:
给定n个子串和一个主串,求有多少个子串在主串中出现过。
(下面的介绍很错略,可参考:http://www.cppblog.com/mythit/archive/2009/04/21/80633.html,本人大多数代码接参考于上面的博客。)
题目解法:AC自动机。
AC自动机,据说是1975年产生自贝尔实验室。多模式匹配算法。
知识储备:trie树、KMP算法思想
操作主要分为三步:
一:建立字典树(trie)。
把n个子串构建字典树,节点需要增加一个变量node * fail,即失败指针。
 1 struct node
2 {
3 node * fail;
4 node * next[kind];
5 int count;
6 node ()
7 {
8 fail=NULL;
9 memset(next,NULL,sizeof(next));
10 count=0;
11 }
12 };

二:建立失败指针。

失败指针分为三类:

1、root的失败指针指向NULL

2、root孩子的失败指针指向root

3、其余节点的失败指针按照以下方法:沿该节点的父亲节点的失败指针查找同样有该节点的节点,把该节点的失败指针指向那个节点的该节点。如果找不到则指向root。如:该节点(1)为‘a',而该节点的父亲节点(2)为’c',则查找'c'的失败指针指向的节点(3),当然节点(3)也为’c',如果节点(3)有’a'这个孩子(节点(4)),则把节点(1)的失败指针指向节点(4),如果节点(3)没有‘a'这个孩子,则沿着沿的失败指针继续查找,直到NULL。则把失败指针指向root。

建立的方法:

由于1、2类节点的失败指针一定,而第3指针是沿着父亲的失败指针查找,所以用队列维护指针。

 1 void buildac(node * root)
2 {
3 int i;
4 root->fail=NULL;
5 q.push(root);
6 while(!q.empty())
7 {
8 node *tp=q.front(),*p;
9 q.pop();
10 for(int i=0;i<26;i++)
11 {
12 if(tp->next[i]!=NULL)
13 {
14 if(tp==root)tp->next[i]->fail=root;
15 else
16 {
17 p=tp->fail;
18 while(p!=NULL)
19 {
20 if(p->next[i]!=NULL)
21 {
22 tp->next[i]->fail=p->next[i];
23 break;
24 }
25 p=p->fail;
26 }
27 if(p==NULL)tp->next[i]->fail=root;
28 }
29 q.push(tp->next[i]);
30 }
31 }
32 }
33 }

三、查询。

查询方法:指针p指向root,沿着主串的字母走,如果该节点没法走则跳到失败指针再走,如果还不能走则再跳直到到达root。如果某一个点匹配成功则沿失败指针统计对应失败指针的count。

int query(node *root)
{
int i=0,cnt=0,index;
node *p=root;
while(s[i])
{
index=s[i]-'a';
while(p->next[index]==NULL && p!=root)p=p->fail;
p=(p->next[index]==NULL)?root:p->next[index];
node *tp=p;
while(tp!=root && tp->count!=-1)
{
cnt+=tp->count;
tp->count=-1;
tp=tp->fail;
}
i++;
}
return cnt;
}
——————————————————————————————————————————————————————————————————————————————————
  1 #include<cstdio>
2 #include<cstring>
3 #include<queue>
4
5 using namespace std;
6 const int kind=26;
7 struct node
8 {
9 node * fail;
10 node * next[kind];
11 int count;
12 node ()
13 {
14 fail=NULL;
15 memset(next,NULL,sizeof(next));
16 count=0;
17 }
18 };
19 typedef node * np;
20 queue<np>q;
21 char keyw[52],s[1000010];
22 node * root=NULL;
23 int t,n;
24 void ins(char s[],node *root)
25 {
26 node *p=root;
27 int i=0,index;
28 while(s[i])
29 {
30 index=s[i]-'a';
31 if(!p->next[index])p->next[index]=new node;
32 p=p->next[index];
33 i++;
34 }
35 p->count++;
36 }
37 void buildac(node * root)
38 {
39 int i;
40 root->fail=NULL;
41 q.push(root);
42 while(!q.empty())
43 {
44 node *tp=q.front(),*p;
45 q.pop();
46 for(int i=0;i<26;i++)
47 {
48 if(tp->next[i]!=NULL)
49 {
50 if(tp==root)tp->next[i]->fail=root;
51 else
52 {
53 p=tp->fail;
54 while(p!=NULL)
55 {
56 if(p->next[i]!=NULL)
57 {
58 tp->next[i]->fail=p->next[i];
59 break;
60 }
61 p=p->fail;
62 }
63 if(p==NULL)tp->next[i]->fail=root;
64 }
65 q.push(tp->next[i]);
66 }
67 }
68 }
69 }
70
71 int query(node *root)
72 {
73 int i=0,cnt=0,index;
74 node *p=root;
75 while(s[i])
76 {
77 index=s[i]-'a';
78 while(p->next[index]==NULL && p!=root)p=p->fail;
79 p=p->next[index];
80 p=(p==NULL)?root:p;
81 node *tp=p;
82 while(tp!=root && tp->count!=-1)
83 {
84 cnt+=tp->count;
85 tp->count=-1;
86 tp=tp->fail;
87 }
88 i++;
89 }
90 return cnt;
91 }
92 int main()
93 {
94 scanf("%d",&t);
95 while(t--)
96 {
97 root=new node;
98 scanf("%d",&n);
99 while(n--)
100 {
101 scanf("%s",keyw);
102 ins(keyw,root);
103 }
104 buildac(root);
105 scanf("%s",s);
106 printf("%d\n",query(root));
107 }
108 return 0;
109 }

HDU2222 Keywords Search__AC自动机的更多相关文章

  1. HDU2222 Keywords Search 【AC自动机】

    HDU2222 Keywords Search Problem Description In the modern time, Search engine came into the life of ...

  2. hdu2222 Keywords Search ac自动机

    地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=2222 题目: Keywords Search Time Limit: 2000/1000 MS ...

  3. HDU2222 Keywords Search [AC自动机模板]

    Keywords Search Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others ...

  4. HDU2222 Keywords Search(AC自动机)

    Keywords Search Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others ...

  5. hdu2222 Keywords Search【AC自动机】

    Keywords Search Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others ...

  6. 【AC自动机】hdu2222 Keywords Search

    AC自动机模板题,给你n个模式串和一个文本串,问你有几个模式串在文本串出现过. 注意防止重复统计 这里推荐一波郭大爷的介绍,简单易懂. http://www.bilibili.com/video/av ...

  7. HDU2222 Keywords Search —— AC自动机

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2222 Keywords Search Time Limit: 2000/1000 MS (Java/O ...

  8. AC自动机讲解+[HDU2222]:Keywords Search(AC自动机)

    首先,有这样一道题: 给你一个单词W和一个文章T,问W在T中出现了几次(原题见POJ3461). OK,so easy~ HASH or KMP 轻松解决. 那么还有一道例题: 给定n个长度不超过50 ...

  9. HDU-2222 Keywords Search 字符串问题 AC自动机

    题目链接:https://cn.vjudge.net/problem/HDU-2222 题意 给一些关键词,和一个待查询的字符串 问这个字符串里包含多少种关键词 思路 AC自动机模版题咯 注意一般情况 ...

随机推荐

  1. 深入浅出!阿里P7架构师带你分析ArrayList集合源码,建议是先收藏再看!

    ArrayList简介 ArrayList 是 Java 集合框架中比较常用的数据结构了.ArrayList是可以动态增长和缩减的索引序列,内部封装了一个动态再分配的Object[]数组 这里我们可以 ...

  2. 有关CSS 定位中的盒装模型、position、z-index的学习心得

    开始整体之前我需要说明两个概念: 第一个就是   一切皆为框  也就是说在HTML中的不管是是块级的还是内联的,都可以认为成块的,唯一的区别就是块的会独自占据一行 第二个文档流:  一个网页可以看作是 ...

  3. Android ADB原理及常用命令

    Android调试桥(ADB, Android Debug Bridge)是一个Android命令行工具,包含在SDK 平台工具包中,adb可以用于连接Android设备,或者模拟器,实现对设备的控制 ...

  4. UNION An Unreferenced Metric for Evaluating Open-ended Story Generation精读

    UNION An Unreferenced Metric for Evaluating Open-ended Story Generation精读 UNION: 一种评估开放故事生成无参考文本依赖me ...

  5. [从源码学设计]蚂蚁金服SOFARegistry之服务上线

    [从源码学设计]蚂蚁金服SOFARegistry之服务上线 目录 [从源码学设计]蚂蚁金服SOFARegistry之服务上线 0x00 摘要 0x01 业务领域 1.1 应用场景 1.1.1 服务发布 ...

  6. [强制]IDE使用UTF-8和LF

    Java 程序开发常用的集成开发环境(IDE)有Eclipse和IntelliJ IDEA.Eclipse是免费开源的,很多早期程序员使用它的比较多.IntelliJ IDEA有社区版和企业版,社区版 ...

  7. Hive表的基本操作

    目录 1. 创建表 2. 拷贝表 3. 查看表结构 4. 删除表 5. 修改表 5.1 表重命名 5.2 增.修.删分区 5.3 修改列信息 5.4 增加列 5.5 删除列 5.6 修改表的属性 1. ...

  8. IP包头分析

    • IP包头是IP协议(网络层,第三层)为数据包添加的头部.        ○ 格式:        ○ ○ 拆开看,每行是4+4+8+16=32bit=4Byte        ○ ip协议最短20 ...

  9. mmall商城分类模块总结

    后台分类model的开发具体功能有:添加分类名称,修改分类名称,查询所有子分类,查询父分类以及它下面的子分类(递归) 需要注意的是,在后台管理进行操作的时候,都需要验证当前用户是否是管理员的角色,不管 ...

  10. 基于 MPI 的快速排序算法的实现

    完整代码: #include <iostream> #include <cstdlib> #include <ctime> #include <algorit ...