题目大意:给定 N 个模式串和一个文本串,求每个模式串在文本串中出现的次数。

题解:文本串在自动机上匹配的过程中,记录下自动机上每一个状态被访问的次数。对于访问到的节点 i,则状态 i 的后缀中存在的匹配串的出现次数都要增加 1。若每次都暴力跳 fail 树的话,复杂度无法得到保证。观察发现,对于每一个模式串,能够对其答案产生贡献的状态一定是 fail 树上的,以该模式串节点为根节点的子树中的节点表示的状态。因此,将 fail 树显示建立出来,在文本串匹配结束后做一次 dfs 即可求出所有的模式串对应的答案了。时间复杂度还是 \(O(N+M)\)。

注意:模式串中可能存在相同的串,若单纯记录自动机上每个节点对应的字符串会 WA 掉(后一个把前一个覆盖掉了)。因此,需要记录每个模式串对应着自动机上的哪个状态节点才行。

代码如下

#include <bits/stdc++.h>
#define pb push_back
using namespace std;
const int maxn=2e5+10;
const int maxm=2e6+10; int n;
int trie[maxn][26],tot=1,match[maxn],fail[maxn],sz[maxn];
vector<int> G[maxn];
queue<int> q;
void insert(char *s,int id){
int now=1,len=strlen(s);
for(int i=0;i<len;i++){
int ch=s[i]-'a';
if(!trie[now][ch])trie[now][ch]=++tot;
now=trie[now][ch];
}
match[id]=now;
}
void build(){
for(int i=0;i<26;i++)trie[0][i]=1;
q.push(1);
while(q.size()){
int u=q.front();q.pop();
for(int i=0;i<26;i++){
if(trie[u][i]){
fail[trie[u][i]]=trie[fail[u]][i];
q.push(trie[u][i]);
}else{
trie[u][i]=trie[fail[u]][i];
}
}
}
}
void query(char *s){
int now=1,len=strlen(s);
for(int i=0;i<len;i++){
now=trie[now][s[i]-'a'];
++sz[now];
}
}
void dfs(int u){
for(auto v:G[u]){
dfs(v);
sz[u]+=sz[v];
}
} char s[maxm]; void read_and_parse(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%s",s);
insert(s,i);
}
build();
scanf("%s",s);
}
void solve(){
query(s);
for(int i=2;i<=tot;i++)G[fail[i]].pb(i);
dfs(1);
for(int i=1;i<=n;i++)printf("%d\n",sz[match[i]]);
}
int main(){
read_and_parse();
solve();
return 0;
}

【模板】AC自动机加强版的更多相关文章

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

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

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

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

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

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

  4. 模板 AC自动机

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

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

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

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

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

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

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

  8. 模板—AC自动机

    #include<iostream> #include<cstdio> #include<cstring> using namespace std; struct ...

  9. 模板——AC自动机

    传送门:QAQQAQ 定义nxt[u]=v表示从u开始不断沿着失配边跳到的第一个是标记点的端点v,那么我们再匹配时沿着last跳,每跳到一个last,它就一定对应一个模式串,所以效率是非常高的. 和K ...

随机推荐

  1. nodejs之express框架商品管理系统登录功能

    1.该系统主要使用express.body-parser.express-session.ejs.mongodb-connect . npm install express --save npm in ...

  2. flutter block回调

    block回调在oc中很常见,到了flutter中仍然有block回调 自定义一个StatefulWidget PageTitle 无参数回调VoidCallback VoidCallback onT ...

  3. 简单方法让input date支持placeholder(包含ios手机端方法)

    <input class="baixin-quan-info-box-time" type="text" onfocus="(this.type ...

  4. overflow-x scroll 内部元素滚动,父级容器代码

    display: -webkit-box; overflow-x: scroll; -webkit-overflow-scrolling: touch;

  5. ALV程序设计

    ALV 全称SAP LIST VIEW, 是SAP所提供的一个强大的数据报表显示工具. ALV显示格式分为GRID及LIST两种,两者所显示数据一致, GRID模式在每个输出字段提供选择按钮,允许用 ...

  6. oracle审计登录失败用户

    使用sys账号连接数据库,然后执行如下步骤: 1.alter system set audit_trail=db scope=spfile; 2.重启数据库服务 3.AUDIT SESSION WHE ...

  7. 接口自动化-python unittest+requests+HTMLrunner

    从2015年毕业入行软件测试,快满4年了,之前技术分享都在百度贴吧上面,现在正式开始在博客中记录工作技术,努力成长,加油 接口测试的步骤1.组装好该接口需要的参数数据2.使用get或post附带参数数 ...

  8. kali安装redis

    下载 wget http://download.redis.io/releases/redis-4.0.11.tar.gz 解压 tar -zxvf redis-4.0.11.tar.gz 切换目录 ...

  9. 第五周课程总结&实验报告(三)

    实验三 String类的应用 实验目的: (1)掌握类String类的使用: (2)学会使用JDK帮助文档: 实验内容: 1.已知字符串:"this is a test of java&qu ...

  10. [Python3] 025 包

    目录 1. 模块 1.1 模块是什么? 1.2 为什么用模块? 1.3 如何定义模块? 1.4 如何使用模块? 1.4.1 例子1 1.4.2 例子2 1.4.3 例子3 1.4.4 例子4 1.4. ...