P8451 题解
显然,题面明摆着让你写一个可持久化 AC 自动机。
但是从空间来说这是不可能的。
想起做 不强制在线 的可持久化数据结构的一种方法,建立“时光树”,具体来说,假若版本 \(x\) 由版本 \(y\) 更改而来,建边 \(x \to y\)。最后在建出的树上遍历并回答询问。
到此我们只需要一个可以支持加入和撤销的 AC 自动机即可。
考虑维护失配树,具体来说,一个字符串出现的次数等于其所有前缀节点在失配树上的祖先中终止节点数量之和,这是一个点修链查,将其转变为子树修单点查,用树状数组维护即可。
#include<bits/stdc++.h>
#define lowbit(x) (x&(-x))
using namespace std;
const int maxn = 1e6+5;
class AC_automaton{
public:
int son[maxn][26],fail[maxn],rt,tot,dfncnt;
vector<int> edge[maxn];//fail 树
vector<int> fa[maxn];//原树上的祖先
int L[maxn],R[maxn],len,now;
void insert(string &s,int pos){
len=s.size(),now=rt;
for(int i=0;i<len;i++){
if(son[now][s[i]-'a']==0) son[now][s[i]-'a']=++tot;
now=son[now][s[i]-'a'];
fa[pos].push_back(now);
}
}
void build(){
queue<int> q;
for(int i=0;i<26;i++) if(son[rt][i]) fail[son[rt][i]]=rt,q.push(son[rt][i]);
while(q.size()>0){
int u=q.front();
q.pop();
for(int i=0;i<26;i++){
if(son[u][i]){
fail[son[u][i]]=son[fail[u]][i];
q.push(son[u][i]);
}
else son[u][i]=son[fail[u]][i];
}
}
for(int i=1;i<=tot;i++){
edge[fail[i]].push_back(i);
}
}
inline void dfs(int u){
L[u]=++dfncnt;
for(int v:edge[u]){
if(!L[v]) dfs(v);
}
R[u]=dfncnt;
}//处理子树信息
}AC;
int tr[maxn];
inline void add(int x,int v){
while(x<=AC.dfncnt) tr[x]+=v,x+=lowbit(x);
}
inline int pre(int x){
int res=0;
while(x>0) res+=tr[x],x-=lowbit(x);
return res;
}
int answer[maxn>>1];
struct Edge{
int v,nxt;
}e[maxn];
int head[maxn>>1],cnt;
void add_edge(int u,int v){
e[++cnt].v=v;
e[cnt].nxt=head[u];
head[u]=cnt;
}
vector<int> Query[maxn>>1];
bitset< 500005 > opt;
inline void dfs(int u){
for(int now:Query[u]){
for(int u:AC.fa[now]){
answer[now]+=pre(AC.L[u]);
}
}
Query[u].clear();
for(int i=head[u];i;i=e[i].nxt){
int now=e[i].v;
if(opt[now]==1){
add(AC.L[AC.fa[now].back()],1);
add(AC.R[AC.fa[now].back()]+1,-1);
}
dfs(now);
if(opt[now]==1){
add(AC.L[AC.fa[now].back()],-1);
add(AC.R[AC.fa[now].back()]+1,1);
}
}
}
inline int found(int u){
return tr[u]==u?u:tr[u]=found(tr[u]);
}
int q;
int main(){
cin>>q;
for(int i=1;i<=q;i++){
tr[i]=i;
int lst,op;
string s;
cin>>op>>lst>>s;
opt[i]=(op==1?1:0);
lst=found(lst);
AC.insert(s,i);
if(opt[i]==1) add_edge(lst,i);
else Query[lst].push_back(i),tr[i]=lst;
}
for(int i=0;i<=q;i++) tr[i]=0;
AC.build();
AC.dfs(AC.rt);
dfs(0);
for(int i=1;i<=q;i++) if(opt[i]==0) cout<<answer[i]<<'\n';
return 0;
}
P8451 题解的更多相关文章
- 2016 华南师大ACM校赛 SCNUCPC 非官方题解
我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...
- noip2016十连测题解
以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...
- BZOJ-2561-最小生成树 题解(最小割)
2561: 最小生成树(题解) Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1628 Solved: 786 传送门:http://www.lyd ...
- Codeforces Round #353 (Div. 2) ABCDE 题解 python
Problems # Name A Infinite Sequence standard input/output 1 s, 256 MB x3509 B Restoring P ...
- 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解
题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...
- 2016ACM青岛区域赛题解
A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Jav ...
- poj1399 hoj1037 Direct Visibility 题解 (宽搜)
http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...
- 网络流n题 题解
学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...
- CF100965C题解..
求方程 \[ \begin{array}\\ \sum_{i=1}^n x_i & \equiv & a_1 \pmod{p} \\ \sum_{i=1}^n x_i^2 & ...
- JSOI2016R3 瞎BB题解
题意请看absi大爷的blog http://absi2011.is-programmer.com/posts/200920.html http://absi2011.is-programmer.co ...
随机推荐
- 用Python画一个冰墩墩!
北京2022年冬奥会的召开,吉祥物冰墩墩着实火了,真的是一墩难求,为了实现冰墩墩的自由,经过资料搜集及参考冰墩墩网上的开源代码(https://github.com/HelloCoder-HaC/bi ...
- python教程1.1:环境安装+代码编辑器安装
1.环境安装 打开官⽹ https://www.python.org/downloads/windows/ 下载中 下载后执⾏,点击下⼀步安装就⾏,注意选择添加Python到当前⽤户环境变量 2.代码 ...
- STM CubeMx不能生成代码的解决方法
在使用STM CubeMx时,遇到不能生成代码的问题,即点击"GENERATE CODE"后,软件没有任何反应. 从网上找到若干解决方案,大概是: 以下是可能的解决方法: 1. 确 ...
- C 语言编程 — 高级数据类型 — 指针
目录 文章目录 目录 前文列表 指针 声明指针 使用指针 NULL 指针 指针的算术运算 指向指针的指针 将指针作为实际参数传入函数 从函数返回指针 一个古老的笑话 前文列表 <程序编译流程与 ...
- Pytorch:以单通道(灰度图)加载图片
以单通道(灰度图)加载图片 如果我们想以单通道加载图片,设置加载数据集时的transform参数如下即可: from torchvision import datasets, transforms t ...
- lodash已死?radash库方法介绍及源码解析 —— 对象方法篇
写在前面 主页有更多其他篇章的方法,欢迎访问查看. 本篇我们介绍radash中对象相关方法的使用和源码解析. assign:递归合并两个对象 使用说明 功能说明:类似于 JavaScript 的 Ob ...
- ModelScope初体验
使用环境:windows 11 前置条件:已安装 anaconda 参考文档:环境安装 step1:新建一个 conda 环境,命名为 modelscope conda create -n model ...
- mp4封装格式与MPEG4Extractor
首先来看mp4的封装格式,mp4数据都被放在一个个的箱子当中,也就是box,box的字节序为网络字节序,也就是大端存储,box由header和body组成,header指明box的大小和类型,body ...
- WPF之单例模式
项目 2019/10/09 问题 2019年10月9日星期三 上午2:46 1.为了实现单例模式,在App类中添加了如下代码,使用了信号量,但是为什么返回;isNew一直为true public ...
- 记录一次由nginx配置引发出来的一系列的缓存问题
问题描述: 在做一个企业微信的移动端项目时,每次修改代码后并且打包.部署完毕,再次打开页面总是会有上一次的缓存,一开始以为是cookie和webStorage缓存导致的,然后每次清除还是有缓存,后来把 ...