洛谷-P5357-【模板】AC自动机(二次加强版)
题目传送门
-------------------------------------- 过年在家无聊补一下这周做的几道AC自动机的模板题
sol:AC自动机,还是要解决跳fail边产生的重复访问,但是这次用last边已经不行了,只能拿76分。我们把跳fail边的过程放到串扫描完之后一次性进行。
- AC自动机
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int MAXN = ;
struct Trie {
int son[MAXN][], fail[MAXN];
int que[MAXN]; int head, tail;
int cnt[MAXN]; int tot, root;
int add_node() {
memset(son[tot], -, sizeof(son[tot]));
cnt[tot] = ;
return tot ++;
}
void init() {
head = tail = ;
tot = ;
root = add_node();
}
int insert(char* s) {
int p = root;
for (int i = ; s[i]; i++) {
int index = s[i] - 'a';
if (son[p][index] == -)
son[p][index] = add_node();
p = son[p][index];
}
return p;
}
void build() {
fail[root] = root;
for (int i = ; i < ; i++) {
if (son[root][i] == -) son[root][i] = root;
else {
fail[son[root][i]] = root;
que[++ tail] = son[root][i];
}
}
while (head != tail) {
int p = que[++ head];
for (int i = ; i < ; i++) {
if (son[p][i] == -) son[p][i] = son[fail[p]][i];
else {
fail[son[p][i]] = son[fail[p]][i];
que[++ tail] = son[p][i];
}
}
}
}
void slove(char* s) {
int p = root;
for (int i = ; s[i]; i++) {
int index = s[i] - 'a';
p = son[p][index];
cnt[p] ++;
}
for (int i = tail; i >= ; i--) {
int p = que[i];
cnt[fail[p]] += cnt[p];
}
}
} ac;
int inde[MAXN]; // 本地运行没什么问题,洛谷叫index就报编译错误
char s[];
int main() {
int n; ac.init();
scanf("%d", &n);
for (int i = ; i <= n; i++) {
scanf("%s", s);
inde[i] = ac.insert(s);
}
ac.build();
scanf("%s", s); ac.slove(s);
for (int i = ; i <= n; i++)
printf("%d\n", ac.cnt[inde[i]]);
return ;
}经过不断地40分、60分、76分,终于搞定了。为了在最后跳fail边的时候保证深度越高的节点越先跳采用了手写队列保留bfs时候的层次关系。网上看到别人的代码据说是用拓扑的,没细看。不过感觉这里的队列就是一个对深度的拓扑排序了。
洛谷-P5357-【模板】AC自动机(二次加强版)的更多相关文章
- 洛谷P3808 & P3796 AC自动机模板
题目:P3808:https://www.luogu.org/problemnew/show/P3808 P3796:https://www.luogu.org/problemnew/show/P37 ...
- 洛谷 - P3966 - 单词 - AC自动机
https://www.luogu.org/problemnew/show/P3966 因为文本串就是字典本身,所以这个和平时的AC自动机不太一样.平时的query要沿着fail树把子树的出现次数依次 ...
- 洛谷.3121.审查(AC自动机 链表)
题目链接 //删掉一个单词需要前移一段位置,用链表维护就好了 复杂度O(sum(len)) #include <cstdio> #include <cstring> #defi ...
- 洛谷 - P2444 - 病毒 - AC自动机
https://www.luogu.org/problemnew/show/P2444 有点恶心,不太明白fail的意义. #include<bits/stdc++.h> using na ...
- 洛谷 P3804 [模板] 后缀自动机
题目:https://www.luogu.org/problemnew/show/P3804 模仿了一篇题解,感觉很好写啊. 代码如下: #include<cstdio> #include ...
- 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)
To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...
- 【洛谷 P5357】 【模板】AC自动机(二次加强版)(AC自动机,差分)
每次匹配都不停跳fail显然太慢了,于是在每个节点和fail指向的点连一条边,构成一棵树,在这棵树上差分一下就好了. AC自动机 就这个算法而言其实没用想象中那么难. #include <cst ...
- 【AC自动机】洛谷三道模板题
[题目链接] https://www.luogu.org/problem/P3808 [题意] 给定n个模式串和1个文本串,求有多少个模式串在文本串里出现过. [题解] 不再介绍基础知识了,就是裸的模 ...
- 洛谷-P3796-【模板】AC自动机(加强版)
题目传送门 -------------------------------------- 过年在家无聊补一下这周做的几道AC自动机的模板题 sol:AC自动机,在fail边的基础上再加一个last边, ...
随机推荐
- [题解] Luogu P4245 [模板]任意模数NTT
三模NTT 不会... 都0202年了,还有人写三模NTT啊... 讲一个好写点的做法吧: 首先取一个阀值\(w\),然后把多项式的每个系数写成\(aw + c(c < w)\)的形式,换句话说 ...
- 十分简明易懂的FFT(快速傅里叶变换)
https://blog.csdn.net/enjoy_pascal/article/details/81478582 FFT前言快速傅里叶变换 (fast Fourier transform),即利 ...
- Linux环境创建交换分区
最近在准备在移动端跑一下深度学习训练好的模型,在RK3399的板子上安装scipy时报错.网上查了一下,由于内存不足导致,做个交换分区就搞定了.那么如何做交换分区呢.话不多说,直接开撸. ------ ...
- VS2019企业版产品密钥
Visual Studio 2019 Enterprise产品密钥(激活码) BF8Y8-GN2QH-T84XB-QVY3B-RC4DF
- Social LSTM 实现代码分析
----- 2019.8.5更新 实现代码思维导图 ----- ----- 初始原文 ----- Social LSTM最早提出于文献 "Social LSTM: Human Traject ...
- VUE- iView组件框架的使用
VUE- iView组件框架的使用 1. 下载iView 工程. 引用:https://www.iviewui.com/
- UML-什么是GRASP?
1.定义 GRASP:General Responsibility Assignment Software Pattern,即通用职责分配软件模式,使用职责进行OO设计的学习工具. 2.本书目标 1) ...
- Opencv中的轮廓(不全)
1.初识轮廓 为了准确,要使用二值化图像.在寻找轮廓之前,要进行阈值化处理,或者Canny边界检测. 查找轮廓的函数会修改原始图像.如果你在找到轮廓之后还想使用原始图像的话,你应该将原始图像存储到其他 ...
- vue 动画框架Animate.css @keyframes
<script src="vue.js"></script> <link rel="stylesheet" href=" ...
- JXCPC 试题册
JXCPC 试题册 Input file: standard input Output file: standard output Time limit: 1s Memory limit: 256 m ...