KMP 自动机,孤独的自动机(同时也是CF1721E的题解)
给定字符串 \(s\),以及 \(q\) 个串 \(t_i\),求将 \(s\) 分别与每个 \(t_i\) 拼接起来后,最靠右的 \(|t_i|\) 个前缀的 border 长度。询问间相互独立。
\(|s|\leq 10^6, q \leq 10^5, |t_i|\leq 10\) 。
(题面来自洛谷)
看到 border ,第一反应就是 KMP 。又想到 KMP 的 next 数组就是干这件事的,于是就有了一个很逊的想法:每次当做 \(t\) 真的接到了 \(s\) 的后面,对 \(t\) 的字符做 KMP 。看起来复杂度很对,但由于要往回跳,不出七个测试点就会超时。
思考一下,如果跳到了 s 以内的字符,那么实际上跳到哪里是固定的。由于我们只需要对 t 中字符匹配,所以完全可以只存储跳到 s 中每个字符时最终会跳到哪里。
发现 AC 自动机就是干这件事的,于是我们可以对单个字符串建立 AC 自动机。无聊的人类将单个串的 AC 自动机叫做 KMP 自动机。
很棒的一点是由于 AC 自动机单个字符的构建是 \(O(1)\) 的,所以我们可以直接按照上面的很逊的方式构建 AC 自动机。预处理复杂度为 \(O(|S|)\) ,单词询问复杂度为\(O(|T|)\)。
这个优化的本质是将 KMP 中往回跳的路径用 AC 自动机的构造方式进行压缩。
要处理的地方是 \(s\) 与 \(t\) 的交界处。 \(s\) 的最后一个字符的儿子要进行更改,过后也要记得还原。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn =(1 << 20) + 5;
int qian[maxn];
int ch[maxn][26], col[maxn], tot;
int fail[maxn];
void add(string s)
{
int n = s.size(), u = 0;
for(int i = 1;i < n;i ++)
{
int p = s[i] - 'a';
if(!ch[u][p]) ch[u][p] = ++ tot;
u = ch[u][p];
}
col[u] ++;
}
void build()
{
queue<int> q;
for(int i = 0;i < 26;i ++) if(ch[0][i]) q.push(ch[0][i]);
while(!q.empty())
{
int u = q.front();
q.pop();
for(int i = 0;i < 26;i ++)
{
if(!ch[u][i]) ch[u][i] = ch[fail[u]][i];
else fail[ch[u][i]] = ch[fail[u]][i],q.push(ch[u][i]);
}
}
}
int yuan[27];
int main(){
freopen("text.in", "r", stdin);
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
string s;
cin >> s;
int n = s.size();
s = ' ' + s;
add(s);
build();
int Q;
cin >> Q;
while(Q --)
{
string t;
cin >> t;
int m = t.size();
t = ' ' + t;
int j = ch[n - 1][s[n] - 'a'];
int p = tot;
for(int i = 0;i < 26;i ++) yuan[i] = ch[tot][i];
for(int i = 1;i <= m;i ++)
{
j = ch[j][t[i] - 'a'];
ch[tot][t[i] - 'a'] = tot + 1;
fail[tot + 1] = ch[fail[tot]][t[i] - 'a'];
cout << j << ' ';
tot ++;
for(int i = 0;i < 26;i ++) ch[tot][i] = ch[fail[tot]][i];
}
for(int i = 0;i < 26;i ++) ch[p][i] = yuan[i];
for(int i = p + 1;i <= tot + 1;i ++)
{
for(int j = 0;j < 26;j ++) ch[i][j] = 0;
if(i != p) fail[i] = 0;
}
tot = p;
cout << endl;
}
return 0;
}
KMP 自动机,孤独的自动机(同时也是CF1721E的题解)的更多相关文章
- 【Luogu3804】【模板】后缀自动机(后缀自动机)
[Luogu3804][模板]后缀自动机(后缀自动机) 题面 洛谷 题解 一个串的出现次数等于\(right/endpos\)集合的大小 而这个集合的大小等于所有\(parent\)树上儿子的大小 这 ...
- 【BZOJ4032】[HEOI2015]最短不公共子串(后缀自动机,序列自动机)
[BZOJ4032][HEOI2015]最短不公共子串(后缀自动机,序列自动机) 题面 BZOJ 洛谷 题解 数据范围很小,直接暴力构建后缀自动机和序列自动机,然后直接在两个自动机上进行\(bfs\) ...
- 模板—字符串—后缀自动机(后缀自动机+线段树合并求right集合)
模板—字符串—后缀自动机(后缀自动机+线段树合并求right集合) Code: #include <bits/stdc++.h> using namespace std; #define ...
- KMP,HASH,Trie,AC自动机
我做个总结算了下午看了一下AC自动机和学习我的大生物(当然是多谢鑫神了)..完了要崩.. 1 KMP 只要是学过的人都觉得比较简单吧 但是学不会的人就感觉很难了,我是那种顿悟的然后感觉非常简单的人过程 ...
- Aho_Corasick自动机(AC自动机)
首先,AC自动机不是Accept自动机,别以为把这段代码复制到OJ上就全都自动AC了…… 其实这玩意是Aho-Corasick 造出来的,所以你懂的. 那么这玩意能干嘛咧? •字符串的匹配问题 •多串 ...
- 后缀自动机&回文自动机学习笔记
在学了一天其实是边学边摆之后我终于大概$get$后缀自动机了,,,就很感动,于是时隔多年我终于决定再写篇学习笔记辽$QwQ$ $umm$和$FFT$学习笔记一样,这是一篇单纯的$gql$的知识总结博, ...
- 后缀自动机/回文自动机/AC自动机/序列自动机----各种自动机(自冻鸡) 题目泛做
题目1 BZOJ 3676 APIO2014 回文串 算法讨论: cnt表示回文自动机上每个结点回文串出现的次数.这是回文自动机的定义考查题. #include <cstdlib> #in ...
- 【AC自动机】AC自动机
Definition & Solution AC自动机是一种多模式串的字符串匹配数据结构,核心在于利用 fail 指针在失配时将节点跳转到当前节点代表字符串的最长后缀子串. 首先对 模式串 建 ...
- D. Match & Catch 后缀自动机 || 广义后缀自动机
http://codeforces.com/contest/427/problem/D 题目是找出两个串的最短公共子串,并且在两个串中出现的次数只能是1次. 正解好像是dp啥的,但是用sam可以方便很 ...
- 牛客多校第四场 I string 后缀自动机/回文自动机
这个回文自动机的板有问题,它虽然能过这道题,但是在计算size的时候会出锅! 题意: 求一个字符串中本质不同的连续子串有几个,但是某串和它反转后的字符串算一个. 题解: 要注意的是,一般字符串题中的“ ...
随机推荐
- Tomcat put 漏洞批量工具
工具下载 https://share.weiyun.com/96ffd3bf26b09ffece8d01317f3b3efb
- node.js发送短信验证码(附带60秒倒计时插件)
推荐一个简单且功能齐全的发送短信验证码接口1.安装下载后的SDK只包含一个zhenzisms.js文件,直接导入到工程中即可使用.下载 2.用法引入模块 const zhenzismsClient = ...
- Spring入门之使用 spring 的 IOC 解决程序耦合(Spring环境搭建)(03-01)
3.1 案例的前期准备 1.使用的案例是:账户的业务层和持久层的依赖关系解决(就是有两个账户实现转账之类的事情,后期继续用这个案例)2.准备环境:在开始 spring 的配置之前,我们要先准备一下环境 ...
- Linux文本文件及处理工具
Linux中的文本信息 文本文件 C语言,Java语言等编程文件的源程序语言 文本格式的数据文件 文本格式的文字信息 在Linux下一切皆文件 everything is file,包括目录也是文件的 ...
- Win10解决无法访问其他机器共享的问题【转】
你不能访问此共享文件夹,因为你组织的安全策略阻止未经身份验证的来宾访问.这些策略可帮助保护你的电脑免受网络上不安全设备或恶意设备的威胁.管理员身份执行sc.exe config lanmanworks ...
- DAST精简代码
先训练G:先不计算D的梯度: 判别器输入类型为(源域,0)或者(目标域,1),输出图片为真实图片(源域)的概率值for param in model_D.parameters(): # model_D ...
- 为动态二级域名申请https的免费证书.
前面已经讲过将nginx部署,并注册了免费的二级域名.但将网址发给儿子,儿子说微信已经不能打开http的网址了,所以一想还是研究一下https的证书申请. 网上有很多讲通过,acme的脚本来自动化申请 ...
- 微信小程序开发遇到的注意事项及奇怪事
1.wx.uploadFile上传文件时只支持本地文件(相册或者拍摄的),网络文件不可以,可以将网络文件用wx.downloadFile下载到本地在下载,下载以后会返回一个微信临时地址然后再下载 2. ...
- Vue+Element UI一个下拉框传字典值和对应字典Label
<el-select @change="getDeptName" v-model="form.deptCode"> <el-option v- ...
- Bug的前后台分类及定位技巧
必备工具:Firefox debug工具 一般浏览器F12即可 如何区分页面的bug问题归属:前端or后端 前端bug主要分为3个类别:HTML,CSS,Javascript三类问题 给个最大的区 ...