题面

CF163E e-Government

给 \(n\) 个字符串 \(s_i\) 和 \(q\) 个询问,刚开始字符串都服役。每次操作将集合中的一个字符串设为退役或服役,或查询与文本串 \(S_i\) 的匹配的服役字符串总次数。

数据范围:\(1\le n,q\le 10^5\),\(1\le \sum|s_i|,\sum|S_i|\le 10^6\)。


蒟蒻语

这是个AC自动机的套路题,但是毕竟套路巧妙而且不得不学,所以蒟蒻写一篇题解。


蒟蒻解

当这题的字符串不退役时,这就是AC自动机的模板。

回忆一下蒟蒻们是怎么做的:先建一棵Trie树,在有字符串终止节点的位置 \(tag=1\)。然后考虑到包含一个字符串必然包含一个字符串的后缀,建立 \(fail\) 链成为AC自动机,\(fail\) 链连接节点成为 \(parent\) 树,重算一个节点的 \(tag\) 为它在 \(parent\) 树上到根节点的路径上的节点的 \(tag\) 之和。每次匹配的时候,在AC自动机上跑一遍文本串,累计一下 \(tag\) 即可。

让一个字符串退役,就相当于将该字符串在Trie树上的终止节点 \(p\) 的 \(tag=1\) 变成 \(tag=0\)。建AC自动机重算 \(tag\) 的时候,每个在 \(parent\) 树上到根节点的路径上包含 \(p\) 的节点的 \(tag\) 都会减 \(1\)。容易发现 \(tag\) 减了 \(1\) 的节点,正好就是 \(parent\) 树上 \(p\) 的子树。

这时候就可以做了,巨佬可以写个树链剖分或LinkCutTree。但是考虑到这题只需要操作子树,不需要操作链,所以可以不写轻重链剖分,求每个节点的 \(dfs\) 序及其子树的 \(dfs\) 序区间即可。区间修改、单点查询可以用差分加树状数组。

当然这题有很多细节,而且代码很长,估计能写写调调好久……看蒟蒻代码吧。


代码

#include <bits/stdc++.h>
using namespace std; //Start
typedef long long ll;
typedef double db;
#define mp(a,b) make_pair(a,b)
#define x first
#define y second
#define be(a) a.begin()
#define en(a) a.end()
#define sz(a) int((a).size())
#define pb(a) push_back(a)
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f; //Data
const int N=1e5,M=1e6+1;
int n,at[N];
bool vis[N]; //FenwickTree
int c[M+2];
void add(int x,int v){
for(int i=x+1;i<M+2;i+=i&-i) c[i]+=v;
}
int sum(int x){
int res=0;
for(int i=x+1;i>=1;i-=i&-i) res+=c[i];
return res;
} //ACAM
int cnt=1,ch[M][26];
void insert(int x,string&s){
int p=0;
for(int i=0;i<sz(s);i++){
int c=s[i]-'a';
if(!~ch[p][c]) ch[p][c]=cnt++;
p=ch[p][c];
}
at[x]=p; //记录第x个字符串的终止节点,方便查找dfs序
}
int fa[M],ind,ld[M],rd[M];//[ld,rd)是自动机节点的子树dfs序区间,ld正好是该节点的dfs序
vector<int> e[M];
void Dfs(int p){
ld[p]=ind++;
for(int v:e[p]) Dfs(v);
rd[p]=ind;
}
void build(){
queue<int> q;
for(int c=0;c<26;c++)
if(~ch[0][c]){
fa[ch[0][c]]=0;
e[0].pb(ch[0][c]); //加边建parent树
// cout<<0<<"->"<<ch[0][c]<<'\n';
q.push(ch[0][c]);
} else ch[0][c]=0;
while(sz(q)){
int p=q.front(); q.pop();
for(int c=0;c<26;c++)
if(~ch[p][c]){
fa[ch[p][c]]=ch[fa[p]][c];
e[fa[ch[p][c]]].pb(ch[p][c]); //加边建parent树
// cout<<fa[ch[p][c]]<<"->"<<ch[p][c]<<'\n';
q.push(ch[p][c]);
} else ch[p][c]=ch[fa[p]][c];
}
Dfs(0);
} //Main
int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
int T; cin>>T>>n;
for(int p=0;p<M;p++){
fa[p]=-1;
for(int c=0;c<26;c++) ch[p][c]=-1;
}
for(int i=0;i<n;i++){
string s; cin>>s;
insert(i,s);
}
build();
for(int i=0;i<n;i++) //刚开始字符串都服役
vis[i]=1,add(ld[at[i]],1),add(rd[at[i]],-1);
while(T--){
char c; cin>>c;
if(c=='+'){
int i; cin>>i,--i;
if(vis[i]) continue;
vis[i]=1,add(ld[at[i]],1),add(rd[at[i]],-1);
} else if(c=='-'){
int i; cin>>i,--i;
if(!vis[i]) continue;
vis[i]=0,add(ld[at[i]],-1),add(rd[at[i]],1);
} else if(c=='?'){
string s; cin>>s;
int res=0,p=0;
for(int i=0;i<sz(s);i++){
int c=s[i]-'a';
p=ch[p][c],res+=sum(ld[p]);
}
cout<<res<<'\n';
}
}
return 0;
}

祝大家学习愉快!

题解-CF163E e-Government的更多相关文章

  1. ICPC — International Collegiate Programming Contest Asia Regional Contest, Yokohama, 2018–12–09 题解

    目录 注意!!此题解存在大量假算法,请各位巨佬明辨! Problem A Digits Are Not Just Characters 题面 题意 思路 代码 Problem B Arithmetic ...

  2. Emergency Evacuation 题解

    The Japanese government plans to increase the number of inbound tourists to forty million in the yea ...

  3. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  4. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  5. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  6. Codeforces Round #353 (Div. 2) ABCDE 题解 python

    Problems     # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring P ...

  7. 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解

    题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...

  8. 2016ACM青岛区域赛题解

    A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

  9. poj1399 hoj1037 Direct Visibility 题解 (宽搜)

    http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...

随机推荐

  1. linux云服务搭建七日杀服务器

    目录 准备工作 1.设置swap 2.安装screen 3.安装SteamCmd运行所需环境 4.创建一个用户 steamCMD与七日杀服务器端 1.下载并安装SteamCMD 2.登录steam账号 ...

  2. cosbench使用方法

    前言 cosbench的功能很强大,但是配置起来可能就有点不是太清楚怎么配置了,本篇将梳理一下这个测试的配置过程,以及一些测试注意项目,以免无法完成自己配置模型的情况 安装 cosbench模式是一个 ...

  3. loadrunner 生成随机参数 Radom相关

    我也是刚开始进入测试行业,不过比较幸运的我之前做过开发,所以对代码比较熟悉,对loadrunner没有进行过系统的学习,也是通过自己的摸索慢慢的积累知识. 今天遇到项目中要我做一个压力测试,其中一些参 ...

  4. 2020年SpringCloud 必知的18道面试题

    今天跟大家分享下SpringCloud常见面试题的知识. 1.什么是Spring Cloud? Spring cloud流应用程序启动器是基于Spring Boot的Spring集成应用程序,提供与外 ...

  5. RTP协议解析及H264/H265 音视频RTP打包分析

    一 概述 实时传输协议(Real-time Transport Protocol或简写RTP)是一个网络传输协议,它是由IETF的多媒体传输工作小组1996年在RFC 1889中公布的. RTP协议详 ...

  6. 基于 abp vNext 微服务开发的敏捷应用构建平台 - 框架分析

    总体架构     本平台从技术上采用ABP vNext和.NET Core编写的微服务架构.客户端层主要以现代浏览器为主,适配了PC端和移动端的访问,采用API和应用程序进行交互,同时提供第三方使用的 ...

  7. rocketmq详解-[个人版]-第一章

    一.消息队列概述 1.1.消息队列由来 在运维场景中,我们经常会存在如下场景:一旦出现S1异常,C1将因为S1的影响而异常(C为客户端,s为服务端) 当然可以通过添加多个S的方式,实现高可用.但这样会 ...

  8. 启动时出现错误:*** Warning - bad CRC or NAND

    前面转自:https://www.cnblogs.com/java20130726/archive/2012/06/15/3218570.html 在对NAND Flash烧写了bootstrap和U ...

  9. iOS沙盒文件目录介绍

    1.APP沙盒目录结构简介 首先奉上苹果官方文档: https://developer.apple.com/library/archive/documentation/FileManagement/C ...

  10. Contest 991

    A 先判合法然后容斥. 时间复杂度 \(O\left(1\right)\). B 贪心选最小的实验做成 \(5\) 分. 时间复杂度 \(O\left(n\right)\). 剩下的鸽了.