模板——AC自动机
传送门:QAQQAQ
定义nxt[u]=v表示从u开始不断沿着失配边跳到的第一个是标记点的端点v,那么我们再匹配时沿着last跳,每跳到一个last,它就一定对应一个模式串,所以效率是非常高的。
和KMP一样,我们只需检测ch[u][c]和ch[nxt[u]][c]的下一个字符是否相同,即可进行nxt数组的初始化,即:
从0~25枚举c,令v=ch[u][c]
则nxt[v]=ch[nxt[u]][c]。
这个nxt[v]并不能保证ch[u][c]就一定存在,所以还需要一个while循环一直跳直到找到一个ch[u][c]!=0的端点。出现了一个while,既使代码不够优美,又使效率无法保证.
所以我们直接把所有ch[k][c]=0的端点的ch[k][c]直接连向ch[nxt[k]][c],就好像并差集的一个路径压缩,由于Trie是读完所有模式串后建的,所以这个加边并不会影响Trie,这样就不用担心节点是否存在的问题了(无论如何都会在根节点1上停止,我们先创建一个虚拟节点0,把0的26条边都连在1上,令nxt[1]=0,那么后面无论情况再糟最后也只是nxt[x]=1)。
考虑到这是一个Trie树上的递推,所以我们用BFS搞一搞就好了。
在查询时,只需对于当前字符串不停跳nxt,判断是否是模式串的结尾即可,因为ch[k][c]=0的端点的ch[k][c]直接连向ch[nxt[k]][c],所以不用担心从前往后枚举文本串的前缀会过长。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=(int)(2e9);
const ll INF=(ll)(5e18);
const int N=; //nxt:保存最长的后缀字串
char s[N];
int nxt[N],n,ch[N][],cnt=;
int bl[N],ans=; void make(char *s)
{
int len=strlen(s),u=;
for(int i=;i<len;i++)
{
int c=s[i]-'a';
if(!ch[u][c]) ch[u][c]=++cnt;
u=ch[u][c];
}
bl[u]++;//不能只赋值为1,可能有完全相同的字符串
} void bfs()
{
for(int i=;i<;i++) ch[][i]=;
queue<int> q;
q.push(); nxt[]=;
while(!q.empty())
{
int u=q.front(); q.pop();
for(int i=;i<;i++)
{
if(!ch[u][i]) ch[u][i]=ch[nxt[u]][i];//剪枝
else
{
int v=ch[u][i];
nxt[v]=ch[nxt[u]][i];
q.push(v);
}
}
}
} void query(char *s)
{
int len=strlen(s),u=;
for(int i=;i<len;i++)
{
int c=s[i]-'a';
int k=ch[u][c];
while(k>&&bl[k]!=-)
{
ans+=bl[k];
bl[k]=-;//剪枝
k=nxt[k];
}
u=ch[u][c];
}
printf("%d\n",ans);
} int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%s",s);
make(s);
}
bfs();
scanf("%s",&s);
query(s);
return ;
}
模板——AC自动机的更多相关文章
- luoguP3808[模板]AC自动机(简单版)
传送门 ac自动机模板题,裸的多串匹配 代码: #include<cstdio> #include<iostream> #include<algorithm> #i ...
- luoguP3796[模板]AC自动机(加强版)
传送门 ac自动机模板,可能我写的ac自动机是有点问题的,所以跑的有些慢 暴力跳fail统计 代码: #include<cstdio> #include<iostream> # ...
- 算法模板——AC自动机
实现功能——输入N,M,提供一个共计N个单词的词典,然后在最后输入的M个字符串中进行多串匹配(关于AC自动机算法,此处不再赘述,详见:Aho-Corasick 多模式匹配算法.AC自动机详解.考虑到有 ...
- 模板 AC自动机
题目描述 有$N$ 个由小写字母组成的模式串以及一个文本串$T$ .每个模式串可能会在文本串中出现多次.你需要找出哪些模式串在文本串$T$ 中出现的次数最多. 输入输出格式 输入格式: 输入含多组数据 ...
- 算法竞赛模板 AC自动机
AC自动机基本操作 (1) 在AC自动机中,我们首先将每一个模式串插入到Trie树中去,建立一棵Trie树,然后构建fail指针. (2) fail指针,是穿插在Trie树中各个结点之间的指针,顾名思 ...
- 洛谷.3808/3796.[模板]AC自动机
题目链接:简单版,增强版 简单版: #include <cstdio> #include <cstring> const int N=1e6+5,S=26; char s[N] ...
- 模板—AC自动机
#include<iostream> #include<cstdio> #include<cstring> using namespace std; struct ...
- AC自动机例题
P3808 [模板]AC自动机(简单版) [题目描述] 给定n个模式串和1个文本串,求有多少个模式串在文本串里出现过. #include<bits/stdc++.h> using name ...
- 「kuangbin带你飞」专题十七 AC自动机
layout: post title: 「kuangbin带你飞」专题十七 AC自动机 author: "luowentaoaa" catalog: true tags: - ku ...
随机推荐
- VB.NET利用正則表達式巧妙限制字符输入
版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/u010028869/article/details/37913867 在通常的程序设计中.对 ...
- hysbz3676 回文串 回文自动机
回文自动机模板题 头铁了一下午hdu6599,最后发现自己的板有问题 先放这里一个正确性得到基本确认的板,过两天肝hdu6599 #pragma GCC optimize(2) #include< ...
- 命令学习_nslookup
nslookup 域名 这是最常用最简单的用法,可以直接获得目标域名的IP地址和CNAME. 如下是A记录的返回情况 nslookup命令会采用先反向解释获得使用的DNS服务器的名称,上图中ns.gu ...
- VS2010-MFC(工具栏:工具栏资源及CToolBar类)
转自:http://www.jizhuomi.com/software/215.html 上一节讲了菜单及CMenu类的使用,这一节讲与菜单有密切联系的工具栏. 工具栏简介 工具栏一般位于主框架窗口的 ...
- Java之RabbitMQ(二)多mq配置
场景: springboot单项目,自身使用mq中间件处理一些业务需求,某些业务上又需要消费第三方mq消息,这时候需要我们单项目中配置多套mq,这时候,需要我们自定义多套mq相关连接工厂.模板.监听工 ...
- flexbox属性速览及常见布局实现
CSS3 弹性盒子(Flex Box)弹性盒子是即 CSS2 浮动布局后, CSS3 的一种新的布局模式. CSS3 弹性盒( Flexible Box 或 flexbox),是一种当页面需要适应不同 ...
- Spring AspectJ 切入点语法详解(7)
1.Spring AOP支持的AspectJ切入点指示符 切入点指示符用来指示切入点表达式目的,,在Spring AOP中目前只有执行方法这一个连接点,Spring AOP支持的AspectJ切入点指 ...
- selenium基础(警告框的处理)
selenium基础(警告框的处理) 在webdriver中处理JavaScript所产生的的警告框有三种类型 alert confirm prompt 划转到警告框的方法是:driver.switc ...
- <转>http协议 文件下载原理详解
最近研究了一下关于文件下载的相关内容,觉得还是写些东西记下来比较好.起初只是想研究研究,但后来发现写个可重用性比较高的模块还是很有必要的,我想这也是大多数开发人员的习惯吧. 对于HTTP协议,向服务器 ...
- js 实现vue—引入子组件props传参
参考:https://www.cnblogs.com/xiaohuochai/p/7388866.html 效果 html <!DOCTYPE html> <html> < ...