bzoj 3881 [Coci2015]Divljak fail树+树链的并
题目大意
Alice有n个字符串S_1,S_2...S_n,Bob有一个字符串集合T,一开始集合是空的。
接下来会发生q个操作,操作有两种形式:
“1 P”,Bob往自己的集合里添加了一个字符串P。
“2 x”,Alice询问Bob,集合T中有多少个字符串包含串S_x。(我们称串A包含串B,当且仅当B是A的子串)
Bob遇到了困难,需要你的帮助。
分析
按S建好trie图,跑出fail树
fail树+树链的并
fail树中在一个点子树中的点字符串包含他
于是我们用树链的并修改
用子树求
注意
写rmqLCA不写init()
而且rmqLCA是每次访问都加一次那种序
别跟周围的什么dfn序,入栈出栈序搞混了
还过样例又过自测的5个点数据
什么心态
solution
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <algorithm>
using namespace std;
const int M=2000007;
inline int rd(){
int x=0;bool f=1;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=0;
for(;isdigit(c);c=getchar()) x=x*10+c-48;
return f?x:-x;
}
int n,m;
char s[M];
int tot=0;
int ch[M][26];
int q[M];
int pre[M];
int id[M];
int st[M],ed[M],tdfn;
int g[M],te;
struct edge{int y,nxt;}e[M];
int a[M<<1][23];
int ln[M<<1],T;
int pos[M];
int c[M];
inline int lb(int x){return x&-x;}
void add(int x,int d){
for(;x<=tdfn;x+=lb(x)) c[x]+=d;
}
int get(int x,int y){
int res=0;
for(;y>0;y-=lb(y)) res+=c[y];
for(x--;x>0;x-=lb(x)) res-=c[x];
return res;
}
void addedge(int x,int y){
e[++te].y=y;e[te].nxt=g[x];g[x]=te;
}
void ins(int ii){
int len=strlen(s+1);
int x=0,i,d;
for(i=1;i<=len;i++){
d=s[i]-'a';
if(ch[x][d]) x=ch[x][d];
else x=ch[x][d]=++tot;
}
id[ii]=x;
}
void getfail(){
int h=0,t=1,x,i;
q[1]=0;
while(h^t){
x=q[++h];
for(i=0;i<26;i++){
if(ch[x][i]){
pre[ch[x][i]]=x?ch[pre[x]][i]:0;
q[++t]=ch[x][i];
}
else ch[x][i]=x?ch[pre[x]][i]:0;
}
}
}
void dfs(int x){
a[pos[x]=++T][0]=x;
st[x]=++tdfn;
int p,y;
for(p=g[x];p;p=e[p].nxt){
dfs(e[p].y);
a[++T][0]=x;
}
ed[x]=tdfn;
}
int pt[M],num;
bool cmp(int x,int y){
return st[x]<st[y];
}
void gao(){
int i,x=0,d;
int len=strlen(s+1);
for(i=1;i<=len;i++){
d=s[i]-'a';
x=ch[x][d];
pt[++num]=x;
}
}
int mn(int x,int y){
return st[x]<st[y]?x:y;
}
void init(){
int i,j,l;
for(i=2;i<=T;i++) ln[i]=ln[i>>1]+1;
for(i=T;i>0;i--){
l=ln[T-i+1];
for(j=1;j<=l;j++) a[i][j]=mn(a[i][j-1],a[i+(1<<j-1)][j-1]);
}
}
int LCA(int x,int y){
x=pos[x], y=pos[y];
if(x>y) swap(x,y);
int l=ln[y-x+1];
return mn(a[x][l],a[y-(1<<l)+1][l]);
}
int main(){
int i,kd,x;
n=rd();
for(i=1;i<=n;i++){
scanf("%s",s+1);
ins(i);
}
getfail();
for(i=1;i<=tot;i++) addedge(pre[i],i);
dfs(0);
init();
m=rd();
while(m--){
kd=rd();
if(kd==1){
scanf("%s",s+1);
num=0;
gao();
sort(pt+1,pt+num+1,cmp);
for(i=1;i<=num;i++)
add(st[pt[i]],1);
for(i=2;i<=num;i++)
add(st[LCA(pt[i-1],pt[i])],-1);
}
else{
x=rd();
printf("%d\n",get(st[id[x]],ed[id[x]]));
}
}
return 0;
}
bzoj 3881 [Coci2015]Divljak fail树+树链的并的更多相关文章
- BZOJ 3881: [Coci2015]Divljak [AC自动机 树链的并]
3881: [Coci2015]Divljak 题意:添加新文本串,询问某个模式串在多少种文本串里出现过 模式串建AC自动机,考虑添加一个文本串,走到的节点记录下来求树链的并 方法是按dfs序排序去重 ...
- BZOJ 3881: [Coci2015]Divljak
3881: [Coci2015]Divljak Time Limit: 20 Sec Memory Limit: 768 MBSubmit: 553 Solved: 176[Submit][Sta ...
- bzoj 3881 [Coci2015]Divljak——LCT维护parent树链并
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3881 对 S 建 SAM ,每个 T 会让 S 的 parent 树的链并答案+1:在 T ...
- BZOJ 3881 [COCI2015]Divljak (Trie图+Fail树+树链的并+树状数组维护dfs序)
题目大意: Alice有n个字符串S_1,S_2...S_n,Bob有一个字符串集合T,一开始集合是空的. 接下来会发生q个操作,操作有两种形式: “1 P”,Bob往自己的集合里添加了一个字符串P. ...
- BZOJ 3881 [Coci2015]Divljak(AC自动机+树状数组)
建立AC自动机然后,加入一个串之后考虑这个串的贡献.我们把这个串扔到AC自动机里面跑.最后对经过每一个点到的这个点在fail树的根的路径上的点有1的贡献.求链的并,我们把这些点按DFS序排序,然后把每 ...
- bzoj 3881: [Coci2015]Divljak AC自动机
题目大意: http://www.lydsy.com/JudgeOnline/problem.php?id=3881 题解: 这道题我想出了三种做法,不过只有最后一种能过. 第一种: 首先我们把所有的 ...
- BZOJ 3881[COCI2015]Divljak (AC自动机+dfs序+lca+BIT)
显然是用AC自动机 先构建好AC自动机,当B中插入新的串时就在trie上跑,对于当前点,首先这个点所代表的串一定出现过,然后这个点指向的fail也一定出现过.那么我们把每个点fail当作父亲,建一棵f ...
- 【BZOJ3881】[Coci2015]Divljak fail树+树链的并
[BZOJ3881][Coci2015]Divljak Description Alice有n个字符串S_1,S_2...S_n,Bob有一个字符串集合T,一开始集合是空的. 接下来会发生q个操作,操 ...
- 【bzoj3881】[Coci2015]Divljak AC自动机+树链的并+DFS序+树状数组
题目描述 Alice有n个字符串S_1,S_2...S_n,Bob有一个字符串集合T,一开始集合是空的. 接下来会发生q个操作,操作有两种形式: “1 P”,Bob往自己的集合里添加了一个字符串P. ...
随机推荐
- PayPal为什么从Java迁移到Node.js 性能提高一倍 文件代码减少44%
大家都知道PayPal是另一家迁移到Node.js平台的大型公司,Jeff Harrell的这篇博文 Node.js at PayPal 解释了为什么从Java迁移出来的原因: 开发效率提高一倍(2 ...
- tcp 高性能服务, netty,mqtt
1. io 线程不要有比较长的服务. 全部异步化. [1] netty 权威指南上只是说业务复杂时派发到业务线程池种. 共用的线程池最好都轻量. 多层线程池后, 下层的可以进行隔离. 这个是 mqtt ...
- cocos2d-x的基本动作2
1.基本动作 Cocos2d提供的基本动作:瞬时动作.延时动作.运作速度. 瞬时动作:就是不需要时间,马上就完成的动作.瞬时动作的共同基类是 InstantAction. Cocos2d提供以下瞬时动 ...
- 【数学 技巧】divisor
没考虑重复lcm处理被卡TLE没A真是可惜 题目大意 $n$为$k-可表达的$当且仅当数$n$能被表示成$n$的$k$个因子之和,其中$k$个因子允许相等. 求$[A,B]$之间$k-可表达$的数的个 ...
- CNCF 有哪些具体的项目内容?
前言:CNCF(Cloud Native Computing Foundation)于 2015 年 7 月成立,隶属于 Linux 基金会,初衷围绕“云原生”服务云计算,致力于维护和集成开源技术,支 ...
- Unity基础-Input接口
input 底层的设备输入接口,在开发中很少用到 Input.GetKey() // Update is called once per frame void Update () { if (Inpu ...
- php生成zip压缩文件的方法,支持文件和压缩包路径查找
/* * new creatZip($_dir,$_zipName); *@ _dir是被压缩的文件夹名称,可使用路径,例 'a'或者'a/test.txt'或者'test.txt' *@ _zipN ...
- 《Java并发编程实战》读书笔记一 -- 简介
<Java并发编程实战>读书笔记一 -- 简介 并发的历史 并发的历史,也是人类利用有限的资源去提高生产效率的一个的例子. 设想现在有台计算机,这台计算机具有以下的资源: 单核CPU一个 ...
- 20181210(os,os.path,subprocess,configparser,shutil)
1.os模块 os表示操作系统,该模块主要处理与操作系统相关的操作.最常用的是文件操作:打开,读取,删除,复制,重命名. 重点掌握增删改查的函数操作. import os# 获取当前执行文件所在文件夹 ...
- 小谈python里 列表 的几种常用用法
在python中列表的常用方法主要包括增加,删除,查看和修改.下面以举例子的方法具体说明,首先我们创建两个列表,列表是用[ ]表示的,里面的元素用逗号隔开. a=[‘hello’,78,15.6,‘你 ...