P3796 【模板】AC自动机(加强版) 题解(Aho-Corasick Automation)
题目链接
解题思路
AC自动机模板题。
刚学AC自动机,写一篇博客增强理解。
AC自动机最关键的一点在于,\(fail\)失配指针的构造。
\(fail\)指针指向的地方,是匹配出现错误后进行重新匹配的位置,这说明,从根开始到\(fail\)指针指向的地方这一块字符串,正是我们刚刚失配之前配上的那一块字符串(子串),且为最长子串。这一点和KMP算法相同。
AC代码
#include<stdio.h>
#include<string.h>
int ac[100010][26],cnt=1;
int queue[100010],fail[100010],end[100010];
char a[160][75],m[1000010];
struct {
int num,cnt;
}ans[500],temp;
void push(char a[],int l,int num){//建立trie树,很好理解不再赘述
int i,now=0;
for(i=0;i<l;i++){
int v=a[i]-'a';
if(!ac[now][v])ac[now][v]=cnt++;
now=ac[now][v];
}
end[now]=num;
}
void build(){
int head=0,tail=0,i;//C党手写queue
for(i=0;i<26;i++)if(ac[0][i]){
queue[tail++]=ac[0][i];//push
fail[ac[0][i]]=0;
}
while(head<tail){
int v=queue[head++];//pop
for(i=0;i<26;i++){
if(ac[v][i]){
fail[ac[v][i]]=ac[fail[v]][i];
queue[tail++]=ac[v][i];//push
}
else ac[v][i]=ac[fail[v]][i];
//该节点的失配指针,指向该节点的父节点的失配指针所指向的节点的子节点
//也即,假设ac[v][i]的父节点失配指针指向的节点为E,则
//从根节点到E的这个串,为从根节点到v这个串的最长共同结尾子串
//那么,ac[v][i]的失配指针应当指向E的第i个节点(保证这一位字符相同)
//if和else的作用:一个是失配指针,一个是trie图。
//如果这点没有后续了,只能建立trie图。
//否则,应当建立失配指针。
}
}
}
void query(char a[],int l){
int i,j,now=0;
for(i=0;i<l;i++){
now=ac[now][a[i]-'a'];//沿着建立好的trie图走
for(j=now;j;j=fail[j])ans[end[j]].cnt++;//找到单词末尾并存储个数
}
}
//C党手写快排
int cmp(int x,int y){
if(ans[x].cnt>ans[y].cnt)return 1;
if(ans[x].cnt<ans[y].cnt)return 0;
if(ans[x].num<ans[y].num)return 1;
return 0;
}
void qs(int left,int right){
int i=left,j=right;
if(i>=j)return;
while(i!=j){
for(;i<j;j--)if(cmp(j,left))break;
for(;i<j;i++)if(cmp(left,i))break;
if(i!=j){
temp=ans[i];ans[i]=ans[j];ans[j]=temp;
}
}
j=left;
temp=ans[i];ans[i]=ans[j];ans[j]=temp;
qs(left,i-1);
qs(i+1,right);
}
int main(){
int i,n;
while(scanf("%d",&n)){
if(!n)break;
cnt=1;
for(i=1;i<=n;i++){
scanf("%s",a[i]);
push(a[i],strlen(a[i]),i);//建立trie树
ans[i].num=i;
ans[i].cnt=0;
}
build();//构造AC自动机的fail指针,以及完善trie树成为trie图
scanf("%s",m);
query(m,strlen(m));//询问文本串
//以下为本题特色,不是AC自动机精髓,可跳过
qs(1,n);
printf("%d\n",ans[1].cnt);
printf("%s\n",a[ans[1].num]);
for(i=2;i<n;i++){
if(ans[i].cnt-ans[i-1].cnt)break;
printf("%s\n",a[ans[i].num]);
}
memset(end,0,sizeof(int)*cnt);
memset(fail,0,sizeof(int)*cnt);
memset(ac,0,sizeof(ac));
}
return 0;
}
P3796 【模板】AC自动机(加强版) 题解(Aho-Corasick Automation)的更多相关文章
- luoguP3796[模板]AC自动机(加强版)
传送门 ac自动机模板,可能我写的ac自动机是有点问题的,所以跑的有些慢 暴力跳fail统计 代码: #include<cstdio> #include<iostream> # ...
- HDU 2222 Keywords Search(AC自动机)题解
题意:给你几个keywords,再给你一段文章,问你keywords出现了几次. 思路:这里就要用到多模匹配算法AC自动机了,AC自动机需要KMP和字典树的知识,匹配时是在字典树上,失配我们就要用到类 ...
- luoguP3808[模板]AC自动机(简单版)
传送门 ac自动机模板题,裸的多串匹配 代码: #include<cstdio> #include<iostream> #include<algorithm> #i ...
- 算法模板——AC自动机
实现功能——输入N,M,提供一个共计N个单词的词典,然后在最后输入的M个字符串中进行多串匹配(关于AC自动机算法,此处不再赘述,详见:Aho-Corasick 多模式匹配算法.AC自动机详解.考虑到有 ...
- 模板 AC自动机
题目描述 有$N$ 个由小写字母组成的模式串以及一个文本串$T$ .每个模式串可能会在文本串中出现多次.你需要找出哪些模式串在文本串$T$ 中出现的次数最多. 输入输出格式 输入格式: 输入含多组数据 ...
- 算法竞赛模板 AC自动机
AC自动机基本操作 (1) 在AC自动机中,我们首先将每一个模式串插入到Trie树中去,建立一棵Trie树,然后构建fail指针. (2) fail指针,是穿插在Trie树中各个结点之间的指针,顾名思 ...
- [模板][P3796]AC自动机(加强版)
Description: 输出有哪些模式串在文本串中出现次数最多,这个次数是多少 Hint: 多组数据,$ len_{文本串}<=10^6,\sum len_{模式串} <= 70*150 ...
- 【模板】AC自动机加强版
题目大意:给定 N 个模式串和一个文本串,求每个模式串在文本串中出现的次数. 题解:文本串在自动机上匹配的过程中,记录下自动机上每一个状态被访问的次数.对于访问到的节点 i,则状态 i 的后缀中存在的 ...
- 洛谷.3808/3796.[模板]AC自动机
题目链接:简单版,增强版 简单版: #include <cstdio> #include <cstring> const int N=1e6+5,S=26; char s[N] ...
- HDU 3065 病毒侵袭持续中(AC自动机)题解
题意:要你找到主串中每个模式串的个数. 思路:题目都没说是多组数据,结果没while(~)直接WA了,和上一题差不多,可以用map或者开个数组储存.指针要记得回收内存,不然MLE. #include& ...
随机推荐
- Python import本地模块
无法识别本地模块 在pycharm中选择文件夹Mark Directory as -> Source root. 或者使用sys.path.append()添加文件夹路径 还是报错ImportE ...
- linux通识
linux是服务器应用领域的开源且免费的多用户多任务操作系统的内核. 以下是对上述论断的解释: 操作系统 简言之,操作系统乃是所有计算设备的大管家,小到智能手表,大到航天航空设备,所有需要操控硬件的地 ...
- memcached php
What is Memcached? Free & open source, high-performance, distributed memory object caching syste ...
- Flutter CLI commands All In One
Flutter CLI commands All In One Flutter run key commands. r Hot reload. R Hot restart. h Repeat this ...
- pure CSS waterfall layout
pure CSS waterfall layout 纯 CSS 瀑布流布局 flex layout .container{} .item{} https://caniuse.com/?search=c ...
- 1月加密货币交易所访问量破3亿!NGK生态星空计划、NGK生态所带来双重利好!
据最新数据显示,2021年一月份,加密货币交易所网站的访问量急剧上升.约有3.44亿访问者涌入了加密货币交易所,超过2020年12月的1.96亿访问者总数,创2018年1月以来新高. 加密货币交易所网 ...
- 翻译:《实用的Python编程》02_02_Containers
目录 | 上一节 (2.1 数据类型) | 下一节 (2.3 格式化) 2.2 容器 本节讨论列表(list),字典(dict)和集合(set). 概述 通常,程序必须处理许多对象. 股票的投资组合 ...
- 使用RSEM进行转录组测序的差异表达分析
仍然是两年前的笔记 1. prepare-reference 如果用RSEM对比对后的bam进行转录本定量,则在比对过程中要确保比对用到的索引是由rsem-prepare-reference产生的. ...
- redis slowlog 慢查询日志
设置 config set slowlog-log-slower-than 10000(微秒) //查看redis时间超过上面设置的阀值的key slowlog len 有几个key slowlog ...
- JUC学习
JUC是java.util.concurrent包 并发编程的工具包 并发.并行 并发:多线程操作一个资源 并行:多人一起走 并发编程的本质:充分利用cpu的资源 线程的几个状态 新建 运行 堵塞 等 ...