【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节点以及它子树的值之和.初 ...
随机推荐
- 9.2.1 .net framework下的MVC 控件的封装(上)
在写.net core下mvc控件的编写之前,我先说一下.net framework下我们MVC控件的做法. MVC下控件的写法,主要有如下三种,最后一种是泛型的写法,mvc提供的控件都是基本控件. ...
- CSS代码规范
空格 选择器 与 { 之间必须包含空格. 列表型属性值 书写在单行时,, 后必须跟一个空格. 属性名 与之后的 : 之间不允许包含空格, : 与 属性值 之间必须包含空格. margin: 0; .+ ...
- 无法解决“Microsoft.SharePoint.Security, Version=15.0.0.0,”与“Microsoft.SharePoint.Security, Version=14.0.0.0”之间的冲突
VisualStudio 2013创建控制台项目,.NetFramework选为4.5.生成目标平台:x64.然后添加对Microsoft.SharePoint.dll的引用. 生成项目时," ...
- SQL初级语句
一)SQL是什么? 结构化查询语言(Structured Query Language)简称SQL, 是一种特殊目的的编程语言,是一种数据库查询和程序设计语言,用于存取数据以及查询.更新和管理关系数据 ...
- Android调用webservice的例子
1.需要一个ksoap2-android-assembly-2.5.2-jar-with-dependencies.jar的架包. 2.需要知道webservice的命名空间 // WSDL文档中的命 ...
- MAC的SVN怎么设置允许.a文件上传
首先在mac中svn的安装会去选择Cornerstone 如果遇到这个问题肯定是已经安装并准备上传.a 文件了.首先要清楚svn是默认过滤忽略.a文件的上传的,要想可以上传.a 可以通过这个简单的方法 ...
- nginx端口占用案例分享
这里分享一个案例,问题的原因是反向代理使用不当. 现象 首先描述一下问题的现象.当时的问题是应用启动失败,日志里面报错显示端口占用.我们的应用都是通过脚本发布的,之前发布过多次都没有出现过问题.那么同 ...
- ThinkPHP实现定时任务
项目服务端框架我选用的是ThinkPHP,由于策划案中有需求要定时刷新指定数据,所以在windows平台我使用微软的计划任务调用bat脚本来执行下面的命令来完成 php index.php /Home ...
- 关于web端功能测试的测试方向
一.功能测试 1.1链接测试 链接是web应用系统的一个很重要的特征,主要是用于页面之间切换跳转,指导用户去一些不知道地址的页面的主要手段,链接测试一般关注三点: 1)链接是否按照既定指示那样,确实链 ...
- CentOS7 配置LAMP
这两天要带新同事.没办法,只有现学现卖,又回到Linux的怀抱了.今晚想配置一下LAMP环境,但是之前用的6.6,今晚想闷声做大死,用一次7试试.网上找了很多教程,但是好像转载的都不负责任,有些到下一 ...