HDU3065【AC自动机-AC感言】
Fourth AC zi dong ji(Aho-Corasick Automation) of life
9A(其实不止交了10发...) 感言:
一开始多组数据这种小数据还是...无伤大局,因为改完以后还是wa...
一:
最后发现是wa在构造fail指针的时候在建立临时指针查询有没有匹配到的fail,在没有匹配到的时候,结点的fail的指针要指向根。
二(重要感言):
在查询时,往上回溯fail指针的时候,fail指针是一定会最终回溯到根的,而且,比如当前查询到的主串是ABCDEF,fail指针可能会一直传递最终到根,但是并不是都有效啊!这里还要注意,fail指针传递过去,找到的是子串,还是本来那个串的后缀串,为什么说是子串:如果有模式串ABCD,ABCDEF,主串是ACBDEF,主串到D的时候已经处理掉了ABCD,这个情况下是不会用到fail指针的功效了,或者这里没有有效的后缀串;什么时候会用fail指针呢,如果有模式串CD,BCD,ABCDEF,主串是ACBDEF,那么在主串到D的时候会通过fail指针找到BCD,然后在找到CD,所以我们能得出,fail指针的回溯,当前串(比如ABCD)最后那个D是一直不会变的,可以说fail指针都是D的fail指针!
三:
不要依赖模板...
推荐几个数据:
2
CC
AAA
ooxxCC%dAAAoen....ENDooxxCC%dAAAoen....ENDooxxCC%dAAAoen....END
2
ABCDE
BCD
ABCD
2
ABCDE
BCD
ABCDEF
//#include <bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<queue>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long LL; /*
题意:
求不同的病毒出现的次数,未出现的不需要输出
AAA其中AA出现2次;
思路:
那我存的应该是编号了,编号都不同。
*/ const int N=5e4+10; struct Trie
{
int id;
Trie *next[26],*fail;
};
Trie q[N],*root;
int tol,ans[1010],n;
char ss[1010][51]; Trie* Creat()
{
Trie *p;
p=&q[tol++];
p->fail=NULL;
p->id=0;
for(int i=0; i<26; i++)
p->next[i]=NULL;
return p;
} void Insert(char *str,int id)
{
Trie *p=root;
int index,len=strlen(str);
for(int i=0; i<len; i++)
{
index=str[i]-'A';
if(p->next[index]==NULL)
p->next[index]=Creat();
p=p->next[index];
}
p->id=id;
} void Build_Ac()
{
queue<Trie*>que;
que.push(root);
while(!que.empty())
{
Trie *p=que.front();que.pop();
for(int i=0; i<26; i++)
{
if(p->next[i]!=NULL)
{
if(p==root)
p->next[i]->fail=root;
else
{
Trie *temp=p->fail;
while(temp!=NULL)//找匹配的
{
if(temp->next[i]!=NULL) //找到
{
p->next[i]->fail=temp->next[i];
break;
}
temp=temp->fail;
}
if(temp==NULL) //如果没有找到匹配的,则fail指向根
p->next[i]->fail=root;
}
que.push(p->next[i]);
}
}
}
} char word[2000010];
void Query()
{
int res=0;
int index,len=strlen(word);
Trie *p=root; for(int i=0; i<len; i++)
{
if(!(word[i]>='A'&&word[i]<='Z')){
p=root;
continue;
}
index=word[i]-'A';
while(p->next[index]==NULL && p!=root)
p=p->fail;
p=p->next[index];
if(p==NULL)
p=root;
Trie *temp=p;
while(temp!=root) //回溯到根
{
ans[temp->id]++; //这里这样写没事,因为我不会用到id为0的,任他+
temp=temp->fail;
}
}
for(int i=1; i<=n; i++)
{
if(ans[i])
printf("%s: %d\n",ss[i],ans[i]);
}
} int main()
{
while(~scanf("%d",&n))
{
tol=0;
root=Creat();
for(int i=1; i<=n; i++)
{
ans[i]=0;
scanf("%s",ss[i]);
Insert(ss[i],i);
}
getchar();
Build_Ac();
gets(word);
Query();
}
return 0;
}
;
HDU3065【AC自动机-AC感言】的更多相关文章
- AC自动机(AC automation)
字典树+KMP 参考自: http://www.cppblog.com/mythit/archive/2009/04/21/80633.html ; //字典大小 //定义结点 struct node ...
- 从Trie谈到AC自动机
ZJOI的SAM让我深受打击,WJZ大神怒D陈老师之T3是SAM裸题orz...我还怎么混?暂且写篇`从Trie谈到AC自动机`骗骗经验. Trie Trie是一种好玩的数据结构.它的每个结点存的是字 ...
- 多模字符串匹配算法之AC自动机—原理与实现
简介: 本文是博主自身对AC自动机的原理的一些理解和看法,主要以举例的方式讲解,同时又配以相应的图片.代码实现部分也予以明确的注释,希望给大家不一样的感受.AC自动机主要用于多模式字符串的匹配,本质上 ...
- AC自动机详解(附加可持久化AC自动机)
AC自动机 AC自动机,说白了就是在trie树上跑kmp(其实个人感觉比kmp容易理解).是一种多匹配串,单个主串的匹配.概括来说,就是将多个匹配串构造一个trie树,对于每个trie树的节点构造nx ...
- 浅谈算法——AC自动机
在学习AC自动机之前,你需要两个前置知识:Trie树,KMP 首先我们需要明白,AC自动机是干什么的(用来自动AC的) 大家都知道KMP算法是求单字符串对单字符串的匹配问题的,那么多字符在单字符上匹配 ...
- T2 AC自动机
T2:AC自动机 (ac.cpp) 题目背景 YZD在每天学习20小时的勤奋研究下,终于开发出了AC自动机!但是,这台AC自动机有一些bug,比如两个部件之间经常会出一些莫名其妙的问题,所以他想要随时 ...
- [Alg] 文本匹配-多模匹配-AC自动机
1. 简介 AC自动机是一种多模匹配的文本匹配算法. 如果采用naive的方法,即依次比较文本串s中是否包含模式串p1, p2,...非常耗时.考虑到这些模式串中可能具有相同子串,可以利用已经比较过的 ...
- 【HDU3065】 病毒侵袭持续中(AC自动机)
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission( ...
- hdu3065 病毒侵袭持续中 AC自动机入门题 N(N <= 1000)个长度不大于50的模式串(保证所有的模式串都不相同), 一个长度不大于2000000的待匹配串,求模式串在待匹配串中的出现次数。
/** 题目:hdu3065 病毒侵袭持续中 链接:http://acm.hdu.edu.cn/showproblem.php?pid=3065 题意:N(N <= 1000)个长度不大于50的 ...
随机推荐
- Hadoop文档 索引
Hadoop中文文档 http://hadoop.apache.org/docs/r1.0.4/cn/index.html Hadoop资料整理 http://www.itpub.net/thread ...
- SQL还有多少"理所当然";还有那些"就是这样"
前言废话——sql是程序员的饭碗,繁琐but万能,但能干并不意味着适合干,每当多表关联寻找外键时,我都在经历一种没有选择的痛苦.sql不完美,但长期代码让人无暇顾及完美,再痛苦的呐喊到最后都归于疲倦已 ...
- c#4.5新语法--自动属性和隐式类型
1.自动属性 自动属性是c#中属性定义的两种形式的一种:传统属性定义.自动属性. 1.1 传统属性定义 private int _age; public int ...
- Linux就该这么学--命令集合8(命令行通配符)
1.查看sda开头的所有设备文件: ls /dev/sda* 2.查看sda后面只有一个字符的设备文件: ls /dev/sda? 3.查看sda后面包含0-9数字的设备文件: ls /dev/sda ...
- JS中奇葩的假值
JavaScript中有 6 个值为“假”,这六个值是 false null undefined 0 '' (空字符串) NaN 这里面 false 本身是布尔类型,其它 5 个则不是. 除了这 6 ...
- git (转载)
文章转载 一:Git是什么? Git是目前世界上最先进的分布式版本控制系统. 二:SVN与Git的最主要的区别? SVN是集中式版本控制系统,版本库是集中放在中央服务器的,而干活的时候,用的都是自己的 ...
- Objective-C 学习笔记
1. Hello, World #import <Foundation/Foundation.h> int main() { /* my first program in Objec ...
- 管中窥Vue
博客文章链接:管中窥Vue Vue和Angular.React.js的相同点和不同点? 与React的相同: 都使用了Virtual DOM 提供了响应式和组件化的视图组件 将注意力集中保持在核心库, ...
- 一个selenium笔试题——去哪网首页获取符合要求的url并保存
今天在群里看到这样一个笔试题:请使用任何熟悉的面向对象编程语言,编写代码,获取http://www.qyer.com页面中,所有</a>标签"href"属性值包含英文单 ...
- 小程序observer函数的应用
需求是这样的 就是构建月份的组件中,月份小于10月的时候 显示的数字都是一个位数,需要转换成两位数, 比如8月份是8 ,那就要转换为08 ,同理可得 其他低于十月份的月份也是要这样做: 打开组件的js ...