【BZOJ-3881】Divljak AC自动机fail树 + 树链剖分+ 树状数组 + DFS序
3881: [Coci2015]Divljak
Time Limit: 20 Sec Memory Limit: 768 MB
Submit: 508 Solved: 158
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
a
bc
abc
5
1 abca
2 1
1 bca
2 2
2 3
Sample Output
2
1
HINT
Source
Solution
首先这个题得利用fail树的性质....
这种给出一个串在给出的一坨串中出现次数或者是否出现过,这样显然是利用fail树...
然后就是把路径上的点变成1,询问有多少个1...这个可以利用树状数组维护DFS序得到...
然后这个题就是先把Alice的串建AC自动机并且建出fail树...
然后每得到Bob的串,就在fail树上相应的点上+1,但是直接+1会有重复,所以先对所有的点排序,然后直接将+1标记打在节点上,并对相邻节点的LCA上打上-1标记,这样询问就转化成求子树和。
数据规模比较大,倍增LCA会被卡..
其实正解应该建虚树...这样的复杂度还是比较玄学....建虚树应该是比较保险的方法.
Code
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
inline int read()
{
int x=; char ch=getchar();
while (ch<'' || ch>'') ch=getchar();
while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
return x;
}
#define MAXN 2000100
int N,Q,id[MAXN];
char S[MAXN];
namespace ACMachine
{
struct TrieNode{int son[MAXN][],fail[MAXN],end[MAXN];}trie;
int sz=;
inline void Insert(int x)
{
int now=,len=strlen(S+);
for (int i=; i<=len; i++)
if (trie.son[now][S[i]-'a']) now=trie.son[now][S[i]-'a'];
else now=trie.son[now][S[i]-'a']=++sz,now=sz;
trie.end[now]=;
id[x]=now;
}
inline void Buildfail()
{
queue<int>q; q.push();
while (!q.empty())
{
int now=q.front(); q.pop();
for (int i=; i<; i++)
if (trie.son[now][i])
{
int fa=trie.fail[now];
while (fa && !trie.son[fa][i]) fa=trie.fail[fa];
trie.fail[trie.son[now][i]]=fa? trie.son[fa][i] : ;
q.push(trie.son[now][i]);
}
}
}
}
using namespace ACMachine;
namespace FailTree
{
struct EdgeNode{int next,to;}edge[MAXN<<];
int head[MAXN],cnt;
inline void AddEdge(int u,int v) {cnt++; edge[cnt].to=v; edge[cnt].next=head[u]; head[u]=cnt;}
inline void InsertEdge(int u,int v) {AddEdge(u,v); AddEdge(v,u);}
inline void BuildTree() {for (int i=; i<=sz; i++) InsertEdge(trie.fail[i],i);}
}
using namespace FailTree;
namespace Divide
{
int size[MAXN],deep[MAXN],fa[MAXN],son[MAXN],pl[MAXN],dfn,pre[MAXN],top[MAXN],pr[MAXN];
inline void DFS_1(int now,int last)
{
size[now]=;
for (int i=head[now]; i; i=edge[i].next)
if (edge[i].to!=last)
{
deep[edge[i].to]=deep[now]+;
fa[edge[i].to]=now;
DFS_1(edge[i].to,now);
size[now]+=size[edge[i].to];
if (size[son[now]]<size[edge[i].to]) son[now]=edge[i].to;
}
}
inline void DFS_2(int now,int chain)
{
pl[now]=++dfn; pre[dfn]=now; top[now]=chain;
if (son[now]) DFS_2(son[now],chain);
for (int i=head[now]; i; i=edge[i].next)
if (edge[i].to!=fa[now] && edge[i].to!=son[now])
DFS_2(edge[i].to,edge[i].to);
pr[now]=dfn;
}
inline int LCA(int x,int y)
{
while (top[x]!=top[y])
{
if (deep[top[x]]<deep[top[y]]) swap(x,y);
x=fa[top[x]];
}
return deep[x]<deep[y]? x:y;
}
}
using namespace Divide;
namespace BIT
{
int tree[MAXN];
inline int lowbit(int x) {return x&-x;}
inline void Modify(int p,int d) {for(int i=p; i<=sz; i+=lowbit(i)) tree[i]+=d;}
inline int Query(int p) {int re=; for (int i=p; i; i-=lowbit(i)) re+=tree[i]; return re;}
inline int Query(int l,int r) {return Query(r)-Query(l-);}
}
using namespace BIT;
int st[MAXN],tp,to;
inline bool cmp(int x,int y) {return pl[x]<pl[y];}
int main()
{
N=read();
for (int i=; i<=N; i++) scanf("%s",S+),ACMachine::Insert(i);
ACMachine::Buildfail();
FailTree::BuildTree();
DFS_1(,); DFS_2(,);
Q=read();
while (Q--)
{
int opt=read(),le; char str[MAXN];
switch (opt)
{
case :
scanf("%s",str+); le=strlen(str+); tp=to=;
for (int now=,i=; i<=le; i++)
{
while (now && !trie.son[now][str[i]-'a']) now=trie.fail[now];
now=trie.son[now][str[i]-'a'];
if (now!=) st[++tp]=now;
}
sort(st+,st+tp+,cmp);
st[to]=-; for (int i=; i<=tp; i++) if (st[to]!=st[i]) st[++to]=st[i];
for (int i=; i<=to; i++) Modify(pl[st[i]],);
for (int i=; i<=to; i++) Modify(pl[LCA(st[i-],st[i])],-);
break;
case : int x=read(); printf("%d\n",Query( pl[id[x]] , pr[id[x]] )); break;
}
}
return ;
}
想找个机会整理一下fail树的一些性质....
【BZOJ-3881】Divljak AC自动机fail树 + 树链剖分+ 树状数组 + DFS序的更多相关文章
- 【BZOJ】2434: [Noi2011]阿狸的打字机 AC自动机+树状数组+DFS序
[题意]阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的: l 输入小写 ...
- BZOJ 2434: [Noi2011]阿狸的打字机 [AC自动机 Fail树 树状数组 DFS序]
2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 2545 Solved: 1419[Submit][Sta ...
- BZOJ.2434.[NOI2011]阿狸的打字机(AC自动机 树状数组 DFS序)
题目链接 首先不需要存储每个字符串,可以将所有输入的字符依次存进Trie树,对于每个'P',记录该串结束的位置在哪,以及当前节点对应的是第几个串(当前串即根节点到当前节点):对于'B',只需向上跳一个 ...
- BZOJ 2780 Sevenk Love Oimaster (后缀自动机+树状数组+dfs序+离线)
题目大意: 给你$n$个大串和$m$个询问,每次给出一个字符串$s$询问在多少个大串中出现过 好神的一道题 对$n$个大串建出广义$SAM$,建出$parent$树 把字符串$s$放到$SAM$里跑, ...
- luogu SP8093 后缀自动机+树状数组+dfs序
这题解法很多,简单说几个: 1. 线段树合并,时间复杂度是 $O(nlog^2n)$ 的. 2. 暴力跳 $fail,$ 时间复杂度 $O(n\sqrt n),$ 比较暴力. 3. 建立后缀树后在 $ ...
- BZOJ 1103 [POI2007]大都市meg(树状数组+dfs序)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1103 [题目大意] 给出一棵树,每条边的经过代价为1,现在告诉你有些路不需要代价了, ...
- BZOJ 4765: 普通计算姬 [分块 树状数组 DFS序]
传送门 题意: 一棵树,支持单点修改和询问以$[l,r]$为根的子树的权值和的和 只有我这种不会分块的沙茶不会做这道题吗? 说一点总结: 子树和当然上$dfs$序了,询问原序列一段区间所有子树和,对原 ...
- 【BZOJ-1103】大都市meg 树状数组 + DFS序
1103: [POI2007]大都市meg Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2009 Solved: 1056[Submit][Sta ...
- POJ 3321 Apple Tree (树状数组+dfs序)
题目链接:http://poj.org/problem?id=3321 给你n个点,n-1条边,1为根节点.给你m条操作,C操作是将x点变反(1变0,0变1),Q操作是询问x节点以及它子树的值之和.初 ...
随机推荐
- 高性能 TCP & UDP 通信框架 HP-Socket v3.5.3
HP-Socket 是一套通用的高性能 TCP/UDP 通信框架,包含服务端组件.客户端组件和 Agent 组件,广泛适用于各种不同应用场景的 TCP/UDP 通信系统,提供 C/C++.C#.Del ...
- linux安装中文字体
一.查看系统字体 在开始安装之前,我们先查看系统中已经安装的字体. 要查看系统中已经安装的字体,我们可以使用fc-list命令进行查看.如果系统中没有该命令的话,我们需要先安装相关的软件包. 在cen ...
- Access提示“操作必须使用一个可更新的查询”的解决办法
问题:软件工程师开发了一个asp.net+access网站,本地调试增.删.改和查都没有异常.部署到服务器windows2008 R2的IIS上运行后,查询没有异常.可是在修改操作提交时,产生异常:提 ...
- CSS3新特性应用之字体排印
一.插入换行 ~:表示同辈元素之后指定类型的元素,如;elm1 ~ elm2表示,elm1之后的所有elm2元素,且elm1与elm2都是在同一个父级元素. +:表示同辈元素的兄弟元素. \A:一个空 ...
- canvas学习之API整理笔记(一)
其实canvas本身很简单,就是去学习它的API,多看实例,多自己动手练习,多总结.但是canvas的API实在是有点多,对于初学者来说,可能学到一半就止步不前了.我也有这种感觉,在学习的过程中,编写 ...
- 2D banner
1.这是我第一次发博客咯!看到本文章后不喜勿喷,有什么需要改进的地方请多多指教! 2.今天和大家分享一下2D banner,代码如下,注释都有.因为本地测试和上传到博客环境不太一样,样式变化比较大,样 ...
- ArrayList、Vector、LinkedList的区别联系?
1.ArrayList.Vector.LinkedList类都是java.util包中,均为可伸缩数组. 2.ArrayList和Vector底层都是数组实现的,所以,索引数据快,删除.插入数据慢. ...
- Android Xfermode 学习笔记
一.概述 Xfermode全名transfer-mode,其作用是实现两张图叠加时的混合效果. 网上流传的关于Xfermode最出名的图来源于AndroidSDK的samples中,名叫Xfermod ...
- jQuery 上传头像插件Jcrop的实例
兼容:ie6+,FF,chrome等 示例图: CSS: 说明:图像比例为110:135 下载包里有 jquery.Jcrop.css .jc-demo-box{po ...
- 一个基于Microsoft Azure、ASP.NET Core和Docker的博客系统
2008年11月,我在博客园开通了个人帐号,并在博客园发表了自己的第一篇博客.当然,我写博客也不是从2008年才开始的,在更早时候,也在CSDN和系统分析员协会(之后名为“希赛网”)个人空间发布过一些 ...