题目链接

AC自动机

解题思路

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)的更多相关文章

  1. luoguP3796[模板]AC自动机(加强版)

    传送门 ac自动机模板,可能我写的ac自动机是有点问题的,所以跑的有些慢 暴力跳fail统计 代码: #include<cstdio> #include<iostream> # ...

  2. HDU 2222 Keywords Search(AC自动机)题解

    题意:给你几个keywords,再给你一段文章,问你keywords出现了几次. 思路:这里就要用到多模匹配算法AC自动机了,AC自动机需要KMP和字典树的知识,匹配时是在字典树上,失配我们就要用到类 ...

  3. luoguP3808[模板]AC自动机(简单版)

    传送门 ac自动机模板题,裸的多串匹配 代码: #include<cstdio> #include<iostream> #include<algorithm> #i ...

  4. 算法模板——AC自动机

    实现功能——输入N,M,提供一个共计N个单词的词典,然后在最后输入的M个字符串中进行多串匹配(关于AC自动机算法,此处不再赘述,详见:Aho-Corasick 多模式匹配算法.AC自动机详解.考虑到有 ...

  5. 模板 AC自动机

    题目描述 有$N$ 个由小写字母组成的模式串以及一个文本串$T$ .每个模式串可能会在文本串中出现多次.你需要找出哪些模式串在文本串$T$ 中出现的次数最多. 输入输出格式 输入格式: 输入含多组数据 ...

  6. 算法竞赛模板 AC自动机

    AC自动机基本操作 (1) 在AC自动机中,我们首先将每一个模式串插入到Trie树中去,建立一棵Trie树,然后构建fail指针. (2) fail指针,是穿插在Trie树中各个结点之间的指针,顾名思 ...

  7. [模板][P3796]AC自动机(加强版)

    Description: 输出有哪些模式串在文本串中出现次数最多,这个次数是多少 Hint: 多组数据,$ len_{文本串}<=10^6,\sum len_{模式串} <= 70*150 ...

  8. 【模板】AC自动机加强版

    题目大意:给定 N 个模式串和一个文本串,求每个模式串在文本串中出现的次数. 题解:文本串在自动机上匹配的过程中,记录下自动机上每一个状态被访问的次数.对于访问到的节点 i,则状态 i 的后缀中存在的 ...

  9. 洛谷.3808/3796.[模板]AC自动机

    题目链接:简单版,增强版 简单版: #include <cstdio> #include <cstring> const int N=1e6+5,S=26; char s[N] ...

  10. HDU 3065 病毒侵袭持续中(AC自动机)题解

    题意:要你找到主串中每个模式串的个数. 思路:题目都没说是多组数据,结果没while(~)直接WA了,和上一题差不多,可以用map或者开个数组储存.指针要记得回收内存,不然MLE. #include& ...

随机推荐

  1. NFS 共享存储

    目录 环境准备 NFS服务端 NFS客户端 部署时常见报错 httpd服务 NFS 共享存储的坑 环境准备 主机名 WanIP(Wide Area Network) LanIP(Local Area ...

  2. UML类图设计神器 AmaterasUML 的配置及使用

    最近写论文需要用到UML类图,但是自己画又太复杂,干脆找了个插件,是Eclipse的,也有IDEA的,在这里我简单说下Eclipse的插件AmaterasUML 的配置与使用吧. 点击这里下载Amat ...

  3. Leetcode(23)-合并K个排序链表

    合并 k 个排序链表,返回合并后的排序链表.请分析和描述算法的复杂度. 示例: 输入: [   1->4->5,   1->3->4,   2->6 ] 输出: 1-&g ...

  4. JAVA中高精度金额计算

    一般java代码中遇到高精度金额计算,日常使用bigDecimal类型. 在使用BigDecimal类来进行计算的时候,主要分为以下步骤: 1.用float或者double变量构建BigDecimal ...

  5. Ant-design-vue—— 表单输入框输入很卡问题

    参考:https://blog.csdn.net/weixin_43905402/article/details/106074435 我的问题:vue项目中使用ant-design-vue,表单中输入 ...

  6. WebIDE All In One

    WebIDE All In One web IDE Visual Studio Code vscode Code editing Redefined. Free. Built on open sour ...

  7. PostgreSQL All In One

    PostgreSQL All In One SQL macOS https://www.postgresql.org/download/macosx/ EDB installer PostgreSQL ...

  8. js GC & stack heap

    js GC & stack heap stack 栈,函数执行形成执行栈帧,变量名,指针 heap 堆,非结构化的数据(Object),分配的内存的存储空间 js 垃圾回收机制 https:/ ...

  9. 如何理解NGK的Layer2-侧链?

    对于 NGK来说,Layer-2越来越重要,并成为共识.但是,"Layer-2" 是个不精确的标签.有些人说起 "Layer-2" 时,仅仅指的是 " ...

  10. 人物传记STEPHEN LITAN:去中心化存储是Web3.0生态重要组成

    近期,NGK.IO的开发团队首席技术官STEPHEN LITAN分享了自己对去中心化储存的观点,以下为分享内容. 目前的存储方式主要是集中式存储,随着数据规模和复杂度的迅速增加,集中存储的数据对于系统 ...