[hdu1277]全文检索(AC自动机)

解题关键:AC自动机模板题,注意字符匹配时若无法匹配,直接用%s即可。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int N=12;
 5 const int MAXN=600010;
 6 int num,ans[10020],nn;
 7 bool vis[600010];
 8 bool flag=false;
 9 struct Trie{//数组形式
10     int Next[MAXN][N],Fail[MAXN],End[MAXN],root,tot;//大小为所以匹配字符串的总和
11     int newnode(){//结构体内部用
12         for(int i=0;i<N;i++) Next[tot][i]=-1;
13         End[tot++]=0;
14         return tot-1;
15     }
16     void init(){
17         tot=0;
18         root=newnode();
19     }
20     void insert(char buf[],int x){
21         int len=strlen(buf);
22         int now=root;//now是temp指针
23         for(int i=0;i<len;i++){
24             int k=buf[i]-‘0‘;
25             if(Next[now][k]==-1)  Next[now][k]=newnode();//next数组代表的是下一个字符索引
26             now=Next[now][k];
27         }
28         End[now]=x;//end数组是当前字符串的个数.字典中可能有相同的单词,若只算一次,改为1.
29     }
30     void build(){//构造fail指针,后缀是某些前缀
31         queue<int>que;
32         Fail[root]=root;
33         for(int i=0;i<N;i++){
34             if(Next[root][i]==-1) Next[root][i]=root;
35             else{
36                 Fail[Next[root][i]]=root;
37                 que.push(Next[root][i]);
38             }
39         }
40         while(!que.empty()){//bfs,会将所有的匹配子串都遍历到
41             int now=que.front();
42             que.pop();
43             for(int i=0;i<N;i++){
44                 if(Next[now][i]==-1) Next[now][i]=Next[Fail[now]][i];
45                 else{
46                     Fail[Next[now][i]]=Next[Fail[now]][i];//fail指向最长的
47                     que.push(Next[now][i]);
48                 }
49             }
50         }
51     }
52     void query(char buf[]){
53         int len=strlen(buf),now=root;
54         for(int i=0;i<len;i++){
55             now=Next[now][buf[i]-‘0‘];
56             int temp=now;
57             while(temp!=root){
58                 if(End[temp]&&!vis[temp]) ans[nn++]=End[temp],vis[temp]=true,flag=true;
59                 temp=Fail[temp];
60             }
61         }
62     }
63 };
64
65 Trie ac;
66 char buf[60004],buf2[60004],tmp[6002];
67 int n,m;
68 int main(){
69     while(scanf("%d%d",&m,&n)!=EOF){
70         memset(ans,0,sizeof ans);
71         memset(vis,0,sizeof vis);
72         nn=0;
73         ac.init();
74         int t=0;
75         flag=false;
76         for(int i=1;i<=m;i++){
77             scanf("%s",tmp);
78             strcat(buf,tmp);
79         }
80            for(int i=1;i<=n;i++){
81                scanf("%*s %*s %d] %s",&num,buf2);
82                ac.insert(buf2,num);
83         }
84            ac.build();//不要忘记build
85         ac.query(buf);
86         if(flag){
87             printf("Found key:");
88             for(int i=0;i<nn;i++){
89                 printf(" [Key No. %d]",ans[i]);
90             }
91             printf("\n");
92         }
93         else printf("No key can be found !\n");
94     }
95     return 0;
96 } 
时间: 2024-10-10 01:08:59

[hdu1277]全文检索(AC自动机)的相关文章

HDOJ1277 全文检索(AC自动机)

全文检索 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 1403    Accepted Submission(s): 458 Problem Description 我们大家经常用google检索信息,但是检索信息的程序是很困难编写的:现在请你编写一个简单的全文检索程序. 问题的描述是这样的:给定一个信息流文件,信息完全有数字组成,

杭电ACM1277——全文检索~~AC自动机算法

题目的意思:给你一篇文章,再给你T个字符串,判断这T个字符串有哪些在文章中出现过. 由于文章很大,普通的方法必定超时,所以需要用 AC自动机算法. AC自动机算法是多模匹配算法之一,主要是用于在一篇文章中,找出给定的N个单词在这篇文章中出现的个数. AC自动机算法,我也是刚刚学习,主要是在建立字典树的基础上,增加了失败指针,提高了匹配的效率.而且最难的是失败指针的建立. 它的优点是:最大限度地减少无谓的字符串比较,查询效率比哈希表高. 对于AC自动机算法,可以参考大神的博客:点击打开链接 里面有

暑假集训day9补充(AC自动机)

推荐网站http://blog.csdn.net/niushuai666/article/details/7002823 AC自动机嘛,此AC(aho-corasick)非彼AC(Accepted). 我也不是很会解释 有一题是必须打的hdu2222. #include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int mn=

ac自动机基础模板(hdu2222)

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, th

HDU 2825 Wireless Password AC自动机+dp

训练赛第二场的I题,上完体育课回来就把这题过了,今天训练赛rank1了,还把大大队虐了,而且我还过了这道题 (虽然我也就过了这道题...),第一次在比赛中手写AC自动机还带dp的,心情大好. 给一个字符串集合,求包含该集合超过K个字符的,长度为L的字符串的个数. 显然是在AC自动机上跑dp,设dp[u][L][k]表示当前在结点u,还要走L步,当前状态为k的个数.一开始第三维表示的是包含k个字符串,但是题目要求不含重复的,那就只能状压了.转移为dp[u][L][k]+=dp[v][L-1][nk

HDU 2896-病毒侵袭(ac自动机)

题意: 给定多个模式串,每给一个母串,输出包含模式串的编号,最后输出包含模式串的母串的数量. 分析: ac自动机模板 #include <map> #include <set> #include <list> #include <cmath> #include <queue> #include <stack> #include <cstdio> #include <vector> #include <st

hdu2222 Keywords Search &amp; AC自动机学习小结

传送门:http://http://acm.hdu.edu.cn/showproblem.php?pid=2222 思路:AC自动机入门题,直接上AC自动机即可. 对于构建AC自动机,我们要做的只有三件事: 1)构建字典树 2)构建失败指针 3)构建trie图(这道题好像不做这一步也能A...但是这一步不做是会被卡成O(n^2)的...) 1)第一步还是比较好理解的 根是虚根,边代表字母,那么根到终止节点的路径就是一个字符串,这样对于前缀相同的字符串我们就可以省下存公共前缀的空间. 加入一个模式

hdoj 2896 病毒侵袭(AC自动机)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2896 思路分析:题目为模式匹配问题,对于一个给定的字符串,判断能匹配多少个模式:该问题需要静态建树,另外需要对AC自动机的模板加以修改, 对于每个匹配的模式的最后一个单词的fail指针指向root,即可实现一个字符串进行多次模式匹配: 代码如下: #include <queue> #include <cstdio> #include <cstring> #include &

从Trie谈到AC自动机

ZJOI的SAM让我深受打击,WJZ大神怒D陈老师之T3是SAM裸题orz...我还怎么混?暂且写篇`从Trie谈到AC自动机`骗骗经验. Trie Trie是一种好玩的数据结构.它的每个结点存的是字母,因此得名`字母树`. 出一张图让大家感受下. (image powered by SaiBu NaoCu) 上面那是一棵插入了 ape,app,applicant,application,bake,ban,banana 等词的Trie.红色结点表示接受态. 显然,查找时只需顺着链照下来,插入只需