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& ...
随机推荐
- NFS 共享存储
目录 环境准备 NFS服务端 NFS客户端 部署时常见报错 httpd服务 NFS 共享存储的坑 环境准备 主机名 WanIP(Wide Area Network) LanIP(Local Area ...
- UML类图设计神器 AmaterasUML 的配置及使用
最近写论文需要用到UML类图,但是自己画又太复杂,干脆找了个插件,是Eclipse的,也有IDEA的,在这里我简单说下Eclipse的插件AmaterasUML 的配置与使用吧. 点击这里下载Amat ...
- Leetcode(23)-合并K个排序链表
合并 k 个排序链表,返回合并后的排序链表.请分析和描述算法的复杂度. 示例: 输入: [ 1->4->5, 1->3->4, 2->6 ] 输出: 1-&g ...
- JAVA中高精度金额计算
一般java代码中遇到高精度金额计算,日常使用bigDecimal类型. 在使用BigDecimal类来进行计算的时候,主要分为以下步骤: 1.用float或者double变量构建BigDecimal ...
- Ant-design-vue—— 表单输入框输入很卡问题
参考:https://blog.csdn.net/weixin_43905402/article/details/106074435 我的问题:vue项目中使用ant-design-vue,表单中输入 ...
- WebIDE All In One
WebIDE All In One web IDE Visual Studio Code vscode Code editing Redefined. Free. Built on open sour ...
- PostgreSQL All In One
PostgreSQL All In One SQL macOS https://www.postgresql.org/download/macosx/ EDB installer PostgreSQL ...
- js GC & stack heap
js GC & stack heap stack 栈,函数执行形成执行栈帧,变量名,指针 heap 堆,非结构化的数据(Object),分配的内存的存储空间 js 垃圾回收机制 https:/ ...
- 如何理解NGK的Layer2-侧链?
对于 NGK来说,Layer-2越来越重要,并成为共识.但是,"Layer-2" 是个不精确的标签.有些人说起 "Layer-2" 时,仅仅指的是 " ...
- 人物传记STEPHEN LITAN:去中心化存储是Web3.0生态重要组成
近期,NGK.IO的开发团队首席技术官STEPHEN LITAN分享了自己对去中心化储存的观点,以下为分享内容. 目前的存储方式主要是集中式存储,随着数据规模和复杂度的迅速增加,集中存储的数据对于系统 ...