[luogu2414 NOI2011]阿狸的打字机 (AC自动机)
Solution
我们知道AC自动机上如果有一点A的fail[A]->B那么B为A的一个后缀
那么我们的问题\((x,y)\)就变为在y中有多少个点直接或间接连向x的终止节点
如果写暴力的话就是遍历y的所有点,对于每个点,我们往上暴跳fail,如果遇到x单词的结尾就ans+1
然而我可以利用dfs序和数据结构优美的完成
首先我们求出fail树(树边与fail相反)的dfs序,并将询问按y排序,然后从头扫读入的字符串,扫的时候给每个点对应的dfs序位置+1。
每当扫完一个字符串时,求出这个字符串作为y的贡献。
具体来说就是找到这个字符串对应的x,对每一个x的终止节点,求出子树的权值和即可
Code
//By Menteur_Hxy
#include <queue>
#include <cmath>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define fi first
#define se second
#define Re register
#define Ms(a,b) memset(a,(b),sizeof(a))
#define Ee(i,u) for(Re int i=head[u];i;i=nxt[i])
#define Fo(i,a,b) for(Re int i=(a),_=(b);i<=_;i++)
#define Ro(i,a,b) for(Re int i=(b),_=(a);i>=_;i--)
#define Add(a,b) nxt[++cnt]=head[a],to[cnt]=b,head[a]=cnt
using namespace std;
typedef pair<int,int> PII;
inline int read() {
int x=0,f=1;char c=getchar();
while(!isdigit(c)) {if(c=='-')f=-f;c=getchar();}
while(isdigit(c)) x=(x<<1)+(x<<3)+c-48,c=getchar();
return x*f;
}
const int L=1e5+10;
int m,tot,cnt;
int str[L],nxt[L],to[L],head[L],dfn[L],low[L],ans[L];
char ch[L];
vector <PII> As[L];
queue <int> Q;
struct AC_Automation{
int nd[L][26],fail[L],fa[L],ret;
AC_Automation() {Ms(nd,0);Ms(fail,0);Ms(fa,0);ret=0;}
void ins(char *s) {
int len=strlen(s),now=0,*p;
Fo(i,0,len-1) {
if(s[i]=='P') str[++tot]=now;
else {
if(s[i]=='B') now=fa[now];
else {p=&nd[now][s[i]-'a'];if(!*p)*p=++ret;fa[*p]=now;now=*p;}
}
}
}
void build() {
Fo(i,0,25) if(nd[0][i]) fail[nd[0][i]]=0,Q.push(nd[0][i]);
while(!Q.empty()) {
int now=Q.front(),*p;Q.pop();
Fo(i,0,25) if(*(p=&nd[now][i])) fail[*p]=nd[fail[now]][i],Q.push(*p);
else *p=nd[fail[now]][i];
}
}
}AC;
struct BIT{
int da[L];
BIT() {clear();}
void clear() {Ms(da,0);}
void add(int x,int k) {for(;x<=L;x+=x&-x)da[x]+=k;}
int qry(int x) {int res=0;for(;x;x-=x&-x)res+=da[x];return res;}
}T;
void dfs(int u) {
dfn[u]=++tot;
Ee(i,u) dfs(to[i]);
low[u]=tot;
}
int main() {
scanf("%s",ch); AC.ins(ch); AC.build();
m=read();
Fo(i,1,m) {
int x=read(),y=read();
As[y].push_back(PII(x,i));
}
Fo(i,1,AC.ret) Add(AC.fail[i],i); dfs(0);
T.add(dfn[0],1); int now=0,tmp=0;
for(Re int i=0;ch[i];i++) {
if(ch[i]=='P') {
tmp++;
Fo(j,0,As[tmp].size()-1) {
int x=str[As[tmp][j].fi];
ans[As[tmp][j].se]=T.qry(low[x])-T.qry(dfn[x]-1);
}
} else if(ch[i]=='B') T.add(dfn[now],-1),now=AC.fa[now];
else now=AC.nd[now][ch[i]-'a'],T.add(dfn[now],1);
}
Fo(i,1,m) printf("%d\n",ans[i]);
return 0;
}
[luogu2414 NOI2011]阿狸的打字机 (AC自动机)的更多相关文章
- 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序 + 树状数组 )
一个串a在b中出现, 那么a是b的某些前缀的后缀, 所以搞出AC自动机, 按fail反向建树, 然后查询(x, y)就是y的子树中有多少是x的前缀. 离线, 对AC自动机DFS一遍, 用dfs序+树状 ...
- 【BZOJ2434】[NOI2011]阿狸的打字机 AC自动机+DFS序+树状数组
[BZOJ2434][NOI2011]阿狸的打字机 Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P ...
- [NOI2011]阿狸的打字机 --- AC自动机 + 树状数组
[NOI2011] 阿狸的打字机 题目描述: 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机. 打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母.经阿狸研究发现, ...
- bzoj 2434 [Noi2011]阿狸的打字机 AC自动机
[Noi2011]阿狸的打字机 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 4001 Solved: 2198[Submit][Status][D ...
- BZOJ2434: [Noi2011]阿狸的打字机(AC自动机 树状数组)
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 4140 Solved: 2276[Submit][Status][Discuss] Descript ...
- BZOJ2434[Noi2011]阿狸的打字机——AC自动机+dfs序+树状数组
题目描述 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的: l 输入小 ...
- [NOI2011]阿狸的打字机——AC自动机之fail树的利用
Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的 ...
- 【BZOJ】2434: [Noi2011]阿狸的打字机 AC自动机+树状数组+DFS序
[题意]阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的: l 输入小写 ...
随机推荐
- 臣妾做不到啊---记团队内首次尝试HOLACRACY管理会议
"易穷则变,变则通.通则久". --<系辞传>下篇的第二章 实践敏捷方法接近两年,瓶颈效应逐渐显现.计穷力竭之时.有幸了解到HOLACRACY.购买了市面上唯一一本中文 ...
- 前端页面a标签嵌套a标签效果的两种解决方案
这是由工作中的一个小改动需求得到的这个解决方案的:那个需求是这样的,如图: 需求原来是球队名字没有点击功能的,而蓝色方框两队之间的比赛点击的时候会跳转到比赛文字直播页面.现在需要要求点击球队名字要跳转 ...
- PHP中JSON的应用
文章来源:PHP开发学习门户 地址: http://www.phpthinking.com/archives/513 互联网的今天,AJAX已经不是什么陌生的词汇了.说起AJAX,可能会马上想起因R ...
- spring:按照Bean的名称自动装配User
本实例将介绍如何按照Bean 的名称自动装配 User 对象! <bean> 元素的 autowire 属性负责自动装配 <bean> 标签,定义 JavaBean 的属性.这 ...
- Tunnel Warfare(树状数组+二分)
http://poj.org/problem?id=2892 题意:输入n,m.n代表数轴的长度,m代表操作数. D x: 摧毁点x Q x: 询问村庄x最左与最右没有被摧毁的点的距离 R :恢复最 ...
- Vue项目打包部署到apache服务器
vue项目在开发环境下,让项目运行起来,是通过npm run dev命令,原理是在本地搭建了一个express服务器. 但是在服务器上就不是这样的,必须要通npm run build命令来对整个项目进 ...
- ThreadLocal,静态变量,实例变量,局部变量的线程安全
之前都是业务层次开发,现在公司进行的网络编程,一下子要了解太多java底层的东西并进行应用,我现在边学习边应用.由于知识能力有限,在上次发博客时出现了一个小小的纰漏,而这个纰漏被细心的博友发现了. 首 ...
- POJ 2553 Tarjan
题意:如果v点能到的所有点反过来又能到v点,则v点是sink点,排序后输出所有的sink点. 思路:Tarjan缩点,输出所有出度为0的连通块内的点. PS:一定要记得把数组清零!!!!!!!否则自己 ...
- 重装系统后快速安装.NET 3.5
每一次重装系统(Windows 8.1 和Windows 10)之后,最让我头疼的一件事就是配置把一大堆软件装上了.通常我会装好SQL Server之后,把电脑放在工作组安装Visual Studio ...
- wpf,vb,位图剪裁的方法
‘ 貌似WPF对GDI+不提供支持,要达到剪裁图像的方法,可以使用image.clip,’不过clip只是对图片的一个遮挡拦截效果,并不改变本身的图片资源.‘下面的代码提供了剪裁图片资源的方法. Di ...