[NOI 2011][BZOJ 2434] 阿狸的打字机
AC自动机 + 树状数组
建成AC自动机后,设end[i]为第i个串的末尾在Trie树上的节点。
可以发现,对于一个询问(x,y),ans等于Trie树上root到end[y]这条链上fail指针指向end[x]的节点数,我们把这些点记为特殊点
因为Trie树上每个节点fail指针仅指向一个值,
因此可以将fail指针反转构建一棵树,以下称为fail树。
于此答案可以等价于在fail树上以end[x]为根的子树中存在的特殊点个数。
然而这样暴力做还是过不了。于是需要一些优化。
可以知道将一个树的节点按dfs序排列后,
树的任意一颗子树的节点在序列中都是连续的一段区间。
我们把特殊的点记为1,非特殊点记为0,
于是求某子树上的特殊点个数可以转化成求某区间的和,
于是就可以用树状数组来优化了。(线段树应该也可以吧,不过似乎会比较麻烦)。
代码:
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstring> using namespace std; #define N ((1<<17)-1)
#define M ((1<<17)-1)
#define lowbit(x) ((x)&(-(x))) queue<int>q;
char s[N];
int end[N],n; struct ACA
{
int cnt;
int fa[N],son[N][],fail[N];
void get_trie()
{
cnt=;
int i,now=,v,p=;
for (i=;i<n;i++)
switch(s[i])
{
case 'P':{end[++p]=now;break;}
case 'B':{now=fa[now];break;}
default:
{
v=s[i]-'a';
if (!son[now][v])
{
son[now][v]=++cnt;
fa[cnt]=now;
}
now=son[now][v];
}
}
for (i=;i<;i++) son[][i]=;
}
void get_fail()
{
int i,j,x;
q.push();
while (!q.empty())
{
x=q.front(),q.pop();
for (i=;i<;i++)
if (son[x][i])
{
for (j=fail[x];j&&!son[j][i];j=fail[j]);
fail[son[x][i]]=son[j][i];
q.push(son[x][i]);
}
}
}
}aca; struct BIT
{
int arr[N],l[N],r[N];
int sum(int i)
{
int re=;
while (i)
{re+=arr[i];i-=lowbit(i);}
return re;
}
void add(int i,int k)
{
while (i<=aca.cnt)
{arr[i]+=k;i+=lowbit(i);}
}
}bit; struct Tree
{
vector<vector<int> >son;
void addedge(int u,int v)
{
son[u].push_back(v);
}
void build()
{
son.resize(aca.cnt+);
for (int i=;i<=aca.cnt;i++)
addedge(aca.fail[i],i);
}
void dfs_order(int x,int &k)
{
bit.l[x]=bit.r[x]=k++;
for (int i=;i<son[x].size();i++)
{
dfs_order(son[x][i],k);
bit.r[x]=max(bit.r[x],bit.r[son[x][i]]);
}
}
}tree; int x[M],ans[M],pre[N],now[N]; inline int val(int x)
{
return bit.sum(bit.r[x])-bit.sum(bit.l[x]-);
} void answer()
{
int m,i,j,y,v,p;
scanf("%d",&m);
memset(now,,sizeof(now));
for (i=;i<=m;i++)
{
scanf("%d%d",&x[i],&y);
x[i]=end[x[i]];
y=end[y];
pre[i]=now[y];
now[y]=i;
}
for (p=,i=;i<n;i++)
{
switch(s[i])
{
case 'P':
{
for (j=now[p];j;j=pre[j])
ans[j]=val(x[j]);
break;
}
case 'B':
{
bit.add(bit.l[p],-);
p=aca.fa[p];
break;
}
default:
{
v=s[i]-'a';
p=aca.son[p][v];
bit.add(bit.l[p],);
}
}
}
for (i=;i<=m;i++)
printf("%d\n",ans[i]);
} int main()
{
scanf("%s",s);
n=strlen(s);
aca.get_trie();
aca.get_fail();
tree.build();
int k=;
tree.dfs_order(,k);
answer();
}
[NOI 2011][BZOJ 2434] 阿狸的打字机的更多相关文章
- AC自动机:BZOJ 2434 阿狸的打字机
2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1834 Solved: 1053[Submit][Sta ...
- bzoj 2434 阿狸的打字机 - Aho-Corasick自动机 - 树状数组
题目传送门 传送站I 传送站II 题目大意 阿狸有一个打字机,它有3种键: 向缓冲区追加小写字母 P:打印当前缓冲区(缓冲区不变) B:删除缓冲区中最后一个字符 然后多次询问第$x$个被打印出来的串在 ...
- BZOJ 2434 阿狸的打字机(fail树)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2434 题意:阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28 ...
- BZOJ 2434 阿狸的打字机
http://www.lydsy.com/JudgeOnline/problem.php?id=2434 思路:建立fail树,并找出dfs序,那剩下要做的就是每次找到一个串的位置,然后询问它的区间里 ...
- bzoj 2434: 阿狸的打字机 fail树+离线树状数组
题目大意: http://www.lydsy.com/JudgeOnline/problem.php?id=2434 题解: 首先我们可以发现这个打字的过程本身就是在Trie上滚来滚去的过程 所以我们 ...
- bzoj 2434 阿狸的打字机 fail树的性质
如果a串是另b串的后缀,那么在trie图上沿着b的fail指针走一定可以走到a串. 而a串在b串里出现多少次就是它是多少个前缀的后缀. 所以把fail边反向建树维护个dfs序就行了. 并不是很难... ...
- BZOJ 2434 阿狸的打字机 | AC自动机
题目戳这里 AC自动机上有神奇的东西叫做fail指针--所有fail指针连起来恰好构成一棵以1为根的树! 而这道题问x在y中出现过多少次,就是问Trie树上根到y的结束节点的路径上有多少节点能通过跳f ...
- BZOJ 2434 阿狸的打字机(ac自动机+dfs序+树状数组)
题意 给你一些串,还有一些询问 问你第x个串在第y个串中出现了多少次 思路 对这些串建ac自动机 根据fail树的性质:若x节点是trie中root到t任意一个节点的fail树的祖先,那么x一定是y的 ...
- 【BZOJ】【2434】【NOI2011】阿狸的打字机
AC自动机+DFS序+BIT 好题啊……orz PoPoQQQ 大爷 一道相似的题目:[BZOJ][3172][TJOI2013]单词 那道题也是在fail树上数有多少个点,只不过这题是在x的fail ...
随机推荐
- NSObject class和NSObject protocol的关系(抽象基类与协议)
[转载请注明出处] 1.接口的实现 对于接口这一概念的支持,不同语言的实现形式不同.Java中,由于不支持多重继承,因此提供了一个Interface关键词.而在C++中,通常是通过定义抽象基类的方式来 ...
- 铺砖问题 (状态压缩dp)
问题描述: 给定m×n个格子,每个格子被染成了黑色或白色.现在要用1×2的砖块覆盖这些格子,要求快于快之间互相不重叠,且覆盖了所有白色的格子(用 . 表示),但不覆盖任意一个黑色的格子(用 x 表示) ...
- chrome表单自动填充导致input文本框背景变成偏黄色问题
你曾遇到过吗? 困扰宝宝好久的问题,本以为是什么插件导致的,结果是chrome浏览器自动填充文本时默认的样式,搜嘎. 一.修改自动填充input文本框背景色: 使用以下代码 可以设置自己的想要的默认文 ...
- bzoj 3035 二分答案+二分图最大匹配
大原来做的一道题,偷懒直接粘的原来的程序 http://www.cnblogs.com/BLADEVIL/p/3433520.html /******************************* ...
- python进行机器学习(三)之模型选择与构建
Scikit-Learn库已经实现了所有基本机器学习的算法,可以直接调用里面库进行模型构建. 一.逻辑回归 大多数情况下被用来解决分类问题(二元分类),但多类的分类(所谓的一对多方法)也适用.这个算法 ...
- 【Python问题解决】关于解决python3.x无法使用PIL库的解决方法
因为PIL库目前只更新到python2.x,故python3.x直接安装PIL库会找不到版本.但是python3.x有一个新的库,可以提供和PIL差不多的功能,也就是pillow库. 本人使用的是py ...
- 海量数据排序——如果有1TB的数据需要排序,但只有32GB的内存如何排序处理?
转载:https://blog.csdn.net/fx677588/article/details/72471357 1.外排序 传统的排序算法一般指内排序算法,针对的是数据可以一次全部载入内存中的 ...
- Linux后台研发面试题
本系列给出了在复习过程中一些C++后台相关面试题,回答内容按照笔者的知识点掌握,故有些问题回答较为简略 1.信号的生命周期 一个完整的信号生命周期可以用四个事件刻画:1)信号诞生:2)信号在进程中注册 ...
- BZOJ 3771 生成函数,FFT
Description 我们讲一个悲伤的故事. 从前有一个贫穷的樵夫在河边砍柴. 这时候河里出现了一个水神,夺过了他的斧头,说: “这把斧头,是不是你的?” 樵夫一看:“是啊是啊!” 水神把斧头扔在一 ...
- pdf2htmlEX安装和配置
1.下载 安装的依赖: sudo yum install cmake gcc gnu-getopt java-1.8.0-openjdk libpng-devel fontforge-devel ca ...