BZOJ 3881 [COCI2015]Divljak (Trie图+Fail树+树链的并+树状数组维护dfs序)
题目大意:
Alice有n个字符串S_1,S_2...S_n,Bob有一个字符串集合T,一开始集合是空的。
接下来会发生q个操作,操作有两种形式:
最先想歪了,想把$T$里的串建自动机,最后失败了..
正解是对Alice的字符串建AC自动机,再建$Fail$树
那么对于操作1,每加入一个字符串,就把这个串放到AC自动机上跑
再把路径上的所有点记下来,新加入的字符串会对连接这些节点的树链上的所有点产生1点贡献
即求树链的并,用树状数组维护$dfs$序
先把这些节点按照$dfs$序排序,然后在树上打差分,树状数组维护前缀和,单点修改
每个节点都+1,$dfs$序中相邻节点的$lca$-1,最后在全局$lca$的父节点-1
询问就是子树查询
#include <cmath>
#include <queue>
#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define NN 2001000
#define MM 1510
#define ll long long
#define dd double
#define uint unsigned int
#define mod 1000000007
#define idx(X) (X-'a')
#define eps (1e-9)
using namespace std; int n,m,cte;
int head[NN];
struct Edge{int to,nxt;}edge[NN];
void ae(int u,int v){
cte++;edge[cte].nxt=head[u];
head[u]=cte,edge[cte].to=v;
}
struct BIT{
int sum[NN*],tot;
void update(int x,int w){
for(int i=x;i<=tot;i+=(i&(-i)))
sum[i]+=w;}
int query(int x){
int ans=;
for(int i=x;i>;i-=(i&(-i)))
ans+=sum[i];
return ans;}
}b;
namespace AC{
int ch[NN][],fail[NN],tot,ed[NN],dep[NN];
void Build_Trie(char *str,int len,int id)
{
int x=;
for(int i=;i<=len;i++){
if(!ch[x][idx(str[i])])
ch[x][idx(str[i])]=++tot,
dep[tot]=dep[x]+;
x=ch[x][idx(str[i])];
}ed[id]=x;
}
void Build_Fail()
{
queue<int>q;
for(int i=;i<;i++)
if(ch[][i]) q.push(ch[][i]);
while(!q.empty())
{
int x=q.front();q.pop();
ae(fail[x],x);
for(int i=;i<;i++)
{
if(ch[x][i]){
fail[ch[x][i]]=ch[fail[x]][i];
q.push(ch[x][i]);
}else{
ch[x][i]=ch[fail[x]][i];
}
}
}
}
};
char str[NN];
namespace T{
int son[NN],sz[NN],tp[NN],fa[NN],dep[NN];
int st[NN],ed[NN],tot;
void dfs1(int u,int dad)
{
for(int j=head[u];j;j=edge[j].nxt){
int v=edge[j].to;
if(v==dad) continue;
fa[v]=u;dep[v]=dep[u]+;
dfs1(v,u);
son[u]=sz[v]>sz[son[u]]?v:son[u];
}sz[u]++;
}
void dfs2(int u)
{
st[u]=++tot;
if(son[u]) tp[son[u]]=tp[u],dfs2(son[u]);
for(int j=head[u];j;j=edge[j].nxt){
int v=edge[j].to;
if(v==fa[u]||v==son[u]) continue;
tp[v]=v,dfs2(v);
}ed[u]=++tot;
}
int LCA(int x,int y)
{
while(tp[x]!=tp[y]){
if(dep[tp[x]]<dep[tp[y]]) swap(x,y);
x=fa[tp[x]];
}return dep[x]<dep[y]?x:y;
}
int stk[NN],num;
int cmp(int x,int y){return st[x]<st[y];}
void update(char *str,int len)
{
int x=,y,ff,v;
for(int i=;i<=len;i++){
v=AC::ch[x][idx(str[i])];
if((!v)) break;
x=v;stk[++num]=x;
}
sort(stk+,stk+num+,cmp);
x=stk[];
if(num==){
b.update(st[x],);
b.update(st[fa[x]],-);
}else{
b.update(st[x],);
for(int i=;i<=num;i++)
{
y=stk[i];ff=LCA(x,y);
b.update(st[y],);
b.update(st[ff],-);
x=stk[i];
}ff=LCA(stk[],stk[num]);
b.update(st[fa[ff]],-);
}
while(num) stk[num--]=;
}
int query(int x)
{return b.query(ed[x])-b.query(st[x]-);}
void solve()
{
dep[]=;dfs1(,-);
tp[]=;dfs2();
scanf("%d",&m);
int fl,x;
b.tot=tot;
for(int i=;i<=m;i++)
{
scanf("%d",&fl);
if(fl==){
scanf("%s",str+);
int len=strlen(str+);
update(str,len);
}else{
scanf("%d",&x);
printf("%d\n",query(AC::ed[x]));
}
}
}
}; int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++){
scanf("%s",str+);
int len=strlen(str+);
AC::Build_Trie(str,len,i);
}AC::Build_Fail();
T::solve();
return ;
}
BZOJ 3881 [COCI2015]Divljak (Trie图+Fail树+树链的并+树状数组维护dfs序)的更多相关文章
- BZOJ3881[Coci2015]Divljak——AC自动机+树状数组+LCA+dfs序+树链的并
题目描述 Alice有n个字符串S_1,S_2...S_n,Bob有一个字符串集合T,一开始集合是空的. 接下来会发生q个操作,操作有两种形式: “1 P”,Bob往自己的集合里添加了一个字符串P. ...
- BZOJ 3881: [Coci2015]Divljak [AC自动机 树链的并]
3881: [Coci2015]Divljak 题意:添加新文本串,询问某个模式串在多少种文本串里出现过 模式串建AC自动机,考虑添加一个文本串,走到的节点记录下来求树链的并 方法是按dfs序排序去重 ...
- BZOJ 3881 [Coci2015]Divljak(AC自动机+树状数组)
建立AC自动机然后,加入一个串之后考虑这个串的贡献.我们把这个串扔到AC自动机里面跑.最后对经过每一个点到的这个点在fail树的根的路径上的点有1的贡献.求链的并,我们把这些点按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 fail树+树链的并
题目大意 Alice有n个字符串S_1,S_2...S_n,Bob有一个字符串集合T,一开始集合是空的. 接下来会发生q个操作,操作有两种形式: "1 P",Bob往自己的集合里添 ...
- 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 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 ...
- (好题)树状数组+离散化+DFS序+离线/莫队 HDOJ 4358 Boring counting
题目传送门 题意:给你一棵树,树上的每个节点都有树值,给m个查询,问以每个点u为根的子树下有多少种权值恰好出现k次. 分析:首先要对权值离散化,然后要将树形转换为线形,配上图:.然后按照右端点从小到大 ...
随机推荐
- ZBrush如何把不同材质赋予同一个模型上
ZBrush 作为最专业的数字雕刻与绘画软件,能够制作出高质量的3D模型,包括模型的颜色贴图和材质属性.不同材质可以改变照明在表面上的反应,以便模型表现出光泽.凹凸.反射.金属性或透明效果.ZBrus ...
- “双十二”年终盛典,Guitar Pro邀您一起倾情共舞
躲过了双十一,躲不过双十二,隐约昨天还是双十一,马上双十二又叕来了,弱弱的问一句“你们的手长粗了来了吗?”在这即将结束的年终盛典里,各商家又将如“双十一”般纷纷使出浑身解数,作为吉他最佳拍档的编曲软件 ...
- javscript中变量的作用域和提升
示例: var a = 1; function foo() { if (!a) { var a = 10; } alert(a); }; foo(); 上面这段代码在运行时会产生 ...
- LeetCode Golang 5. 最长回文子串
5. 最长回文子串 给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为 1000. 示例 1: 输入: "babad" 输出: "bab&quo ...
- 小程序--wepy省市区三级联动选择
产品老哥对项目再一次进行关爱, 新增页面, 新增需求, 很完美........ 不多说, 记录一下新增东西中的省市区联动选择, (这里全国地区信息是在本地, 但不建议这么做, 因为js文件太大.. 建 ...
- BZOJ 3307 雨天的尾巴 (树上差分+线段树合并)
题目大意:给你一棵树,树上一共n个节点,共m次操作,每次操作给一条链上的所有节点分配一个权值,求所有节点被分配到所有的权值里,出现次数最多的权值是多少,如果出现次数相同就输出最小的. (我辣鸡bzoj ...
- code-reading-notes--xml 解析
- Selenium:简单的尝试一下
一.创建maven工程引入依赖 1)创建项目 创建一个简单的maven工程即可 这里我使用jar项目进行简单的演示 2)引入依赖 <dependencies> <dependency ...
- js实现点击复制网页内容(基于execCommand)
通过execCommand方法来实现,当一个HTML文档切换到设计模式 designMode时,文档对象暴露 execCommand 方法,该方法允许运行命令来操纵可编辑区域的内容.大多数命令影响文档 ...
- ASP.NET-优化websit
如何优化一个网站 1.如果是数据库的问题则尝试添加索引.优化SQL语句,如果是算法的问题,则优化算法. 2.如果对于一些不经常改动的页面可以使用静态页技术! 3.对于一些数据不需要及时更新的而且取数据 ...