题目链接

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. Shpfile文件的字段类型说明

    Shpfile文件的字段类型设置如下表所示: 字段类型 字符 字段长度 长整型 N 9 短整型 N 4 浮点型 F 13 双精度 F 19 文本 C 50 特别需要注意的是字段长度,在导出SHP的时候 ...

  2. tensorflow加载ckpt出错

    Issue链接 问题: tensorflow加载ckpt出错 此处原因: 该ckpt文件对应的tensorflow版本过老, 其中的部分内置变量名发生了改变. 提示: Key lstm_o/bidir ...

  3. Python Coding Interview

    Python Coding Interview Python Advanced Use enumerate() to iterate over both indices and values Debu ...

  4. Bastion Host (BH)

    Bastion Host (BH) 堡垒机 堡垒主机是专门设计和构造成承受攻击网络上的专用计算机. 该计算机通常承载单个应用程序,例如代理服务器,并且所有其他服务都将被删除或限制以减少对计算机的威胁. ...

  5. Taro Advanced

    Taro Advanced aro 代码与小程序代码混写 https://nervjs.github.io/taro/docs/hybrid.html https://github.com/NervJ ...

  6. js 增加数组的嵌套层数

    class A {} const proxy = new Proxy(new A(), { get(o, k) { if (!/\d+/.test(k.toString())) return o[k] ...

  7. tslint 忽略对某行代码的检测

    tslint rules class Ajanuw { constructor() { console.log("hello ajanuw"); } } // @ts-ignore ...

  8. Flutter: 显示&关闭系统叠加层ui

    import 'package:flutter/services.dart'; /// 关闭 SystemChrome.setEnabledSystemUIOverlays([]); /// 显示 S ...

  9. 1月加密货币交易所访问量破3亿!NGK生态星空计划、NGK生态所带来双重利好!

    据最新数据显示,2021年一月份,加密货币交易所网站的访问量急剧上升.约有3.44亿访问者涌入了加密货币交易所,超过2020年12月的1.96亿访问者总数,创2018年1月以来新高. 加密货币交易所网 ...

  10. NGK生态商城即将上线官网,推动生态落地应用

    NGK生态商城即将上线官网,以推动生态落地应用.此举意味着NGK生态将跻身区块链顶尖之列,同时,NGK代币.NGK Dapp游戏 "呼叫河马" 以及NGK DeFi项目Baccar ...