题解-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的更多相关文章
- ICPC — International Collegiate Programming Contest Asia Regional Contest, Yokohama, 2018–12–09 题解
目录 注意!!此题解存在大量假算法,请各位巨佬明辨! Problem A Digits Are Not Just Characters 题面 题意 思路 代码 Problem B Arithmetic ...
- Emergency Evacuation 题解
The Japanese government plans to increase the number of inbound tourists to forty million in the yea ...
- 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 ...
随机推荐
- minishell的实现
直接上各个模块的代码,注释都在文档代码中,非常详细,加上最后的Makefile文件完全可以自行运行看懂: main函数一个文件main.c 1 /* 2 minishell实现的功能:简单命令解析.管 ...
- mysql_用命令行备份数据库
MySQL数据库使用命令行备份|MySQL数据库备份命令 例如: 数据库地址:127.0.0.1 数据库用户名:root 数据库密码:pass 数据库名称:myweb 备份数据库到D盘跟目录 mysq ...
- javascript九宫格碰撞检测
JS九宫格碰撞检测这个东西 以前学过 这次主要是做面试项目web版的win10 桌面图片需要用碰撞检测 再写的时候竟然完全忘记了碰撞检测原理 和怎么写 综合来说还是写的太少 今天再学了一下 理 ...
- python-基础入门-2
这里介绍两个,相当于c中的scanf函数 第一个raw_input 1 age=raw_input("how old are you ") 2 print "you ar ...
- 分布式监控系统之Zabbix 使用SNMP、JMX信道采集数据
前文我们了解了zabbix的被动.主动以及web监控相关话题,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/14024212.html:今天我们来了解下zabb ...
- MindManager教程:高中数学函数思维导图怎么画
说起函数,大家应该都不陌生吧,函数不论是在初中还是在高中都是需要重点学习的知识点,不仅仅是重点,更是作为难点曾出现在高考最后一道大题中.那今天我们就来做一个函数思维导图,来简单地了解一下关于函数的一些 ...
- PDF编辑:pdfFactory文本备注功能详解
除了word的doc文件外,PDF也是我们经常接触到的文件格式,经常需要在pdf文件上进行编辑与修改,或者给内容做提示和备注. 文件的文本备注功能可以用pdfFactory来进行,编辑打印PDF一条龙 ...
- 用思维导图软件iMindMap来提高记忆
虽说人的大脑是强大的存储器,但是我们终究没有挖掘出大脑全部的潜能,在记忆时或许因为方式.或许是干扰因素都能够影响我们的记忆力,致使有心无力,快来让思维导图来拯救你的记忆吧. 记忆是经验的关键,思维导图 ...
- Mac book系统的垃圾清理如何进行?
当我们看到电脑发出的内存不足的提示,这就意味着: 1.Mac系统的内存即将被占满 2.电脑将运行缓慢 3.开机速度变慢 很多人使用Mac book一年以后都会发现,它的运行开始逐渐变慢,爱电脑的人在将 ...
- centons 7 清机 脚本
#/bin/bash##################################初始化系统###################setenforce 0 yum install -y yum- ...