Description

阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机。打字机上只有28个按键,分别印有26个小写英文字母和'B'、'P'两个字母。

经阿狸研究发现,这个打字机是这样工作的:

l 输入小写字母,打字机的一个凹槽中会加入这个字母(这个字母加在凹槽的最后)。

l 按一下印有'B'的按键,打字机凹槽中最后一个字母会消失。

l 按一下印有'P'的按键,打字机会在纸上打印出凹槽中现有的所有字母并换行,但凹槽中的字母不会消失。

例如,阿狸输入aPaPBbP,纸上被打印的字符如下:

a

aa

ab

我们把纸上打印出来的字符串从1开始顺序编号,一直到n。打字机有一个非常有趣的功能,在打字机中暗藏一个带数字的小键盘,在小键盘上输入两个数(x,y)(其中1≤x,y≤n),打字机会显示第x个打印的字符串在第y个打印的字符串中出现了多少次。

阿狸发现了这个功能以后很兴奋,他想写个程序完成同样的功能,你能帮助他么?

Input

输入的第一行包含一个字符串,按阿狸的输入顺序给出所有阿狸输入的字符。

第二行包含一个整数m,表示询问个数。

接下来m行描述所有由小键盘输入的询问。其中第i行包含两个整数x, y,表示第i个询问为(x, y)。

Output

输出m行,其中第i行包含一个整数,表示第i个询问的答案。

Sample Input

aPaPBbP

3

1 2

1 3

2 3

Sample Output

2

1

0

HINT

1<=N<=10^5

1<=M<=10^5

输入总长<=10^5

Solution

AC自动机

不知道性质完全做不了

如果AC自动机中的两个串 \(p\) 和 \(s\) ,满足 \(p\) 在 \(s\) 中出现了 \(k\) 次,那么 \(k\) 等于 \(p\) 串结束点在fail树上的子树中有多少个节点属于串 \(s\)

维护树中一个节点的子树和,就随便搞了,我用的BIT

然后就可以离线了

首先把串按照题目含义建出AC自动机

然后getfail

对询问排序

开始算答案,重新跟着给的串走一遍,达到一个点,把它的贡献加入BIT,离开一个点则减去,那么BIT中保存的就一定是当前达到的点到根路径上的点的贡献

(注意,加贡献一定是加在这个点在fail树中的位置,而不是AC自动机上的位置)

所以如果当前到达了一个询问,就可以直接在BIT查答案了

#include<bits/stdc++.h>
#define ui unsigned int
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
const int MAXN=100000+10,MAXM=100000+10;
int ch[MAXN][30],fail[MAXN],n,m,cnt,st[MAXN],e,beg[MAXN],nex[MAXN<<1],to[MAXN<<1],nt,ans[MAXN],ed[MAXN],fa[MAXN],fl[MAXN],ps[MAXN];
char s[MAXN];
std::queue<int> q;
struct node{
int x,y,id;
inline bool operator < (const node &A) const {
return y<A.y;
};
};
node qs[MAXM];
struct BIT{
int C[MAXN];
inline int lowbit(int x)
{
return x&(-x);
}
inline void add(int x,int k)
{
while(x<=nt)C[x]+=k,x+=lowbit(x);
}
inline int sum(int x)
{
int res=0;
while(x>0)res+=C[x],x-=lowbit(x);
return res;
}
};
BIT T;
template<typename T> inline void read(T &x)
{
T data=0,w=1;
char ch=0;
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
x=data*w;
}
template<typename T> inline void write(T x,char ch='\0')
{
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);
putchar(x%10+'0');
if(ch!='\0')putchar(ch);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
inline void insert(int x,int y)
{
to[++e]=y;
nex[e]=beg[x];
beg[x]=e;
}
inline void init()
{
int x=0;
for(register int i=0,lt=strlen(s);i<lt;++i)
if(s[i]=='P')fl[x]=++n,ps[n]=x;
else if(s[i]=='B')x=fa[x];
else if(!ch[x][s[i]-'a'+1])fa[cnt+1]=x,x=ch[x][s[i]-'a'+1]=++cnt;
else x=ch[x][s[i]-'a'+1];
}
inline void getfail()
{
for(register int i=1;i<=26;++i)
if(ch[0][i])q.push(ch[0][i]);
while(!q.empty())
{
int x=q.front();
q.pop();
for(register int i=1,y,z;i<=26;++i)
if(ch[x][i])
{
y=ch[x][i],z=fail[x];
while(z&&!ch[z][i])z=fail[z];
fail[y]=ch[z][i];
q.push(y);
}
}
}
inline void dfs(int x,int f)
{
st[x]=++nt;
for(register int i=beg[x];i;i=nex[i])
if(to[i]==f)continue;
else dfs(to[i],x);
ed[x]=nt;
}
inline void solve()
{
int x=0,nq=1;
for(register int i=0,lt=strlen(s);i<lt;++i)
{
if(s[i]=='P')
while(fl[x]==qs[nq].y)ans[qs[nq].id]=T.sum(ed[ps[qs[nq].x]])-T.sum(st[ps[qs[nq].x]]-1),++nq;
else if(s[i]=='B')T.add(st[x],-1),x=fa[x];
else x=ch[x][s[i]-'a'+1],T.add(st[x],1);
}
}
int main()
{
scanf("%s",s);
init();getfail();
for(register int i=1;i<=cnt;++i)insert(i,fail[i]),insert(fail[i],i);
read(m);
for(register int i=1;i<=m;++i)read(qs[i].x),read(qs[i].y),qs[i].id=i;
dfs(0,-1);
std::sort(qs+1,qs+m+1);
solve();
for(register int i=1;i<=m;++i)write(ans[i],'\n');
return 0;
}

【刷题】BZOJ 2434 [Noi2011]阿狸的打字机的更多相关文章

  1. BZOJ 2434: [Noi2011]阿狸的打字机 [AC自动机 Fail树 树状数组 DFS序]

    2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 2545  Solved: 1419[Submit][Sta ...

  2. BZOJ 2434: [Noi2011]阿狸的打字机( AC自动机 + DFS序 + 树状数组 )

    一个串a在b中出现, 那么a是b的某些前缀的后缀, 所以搞出AC自动机, 按fail反向建树, 然后查询(x, y)就是y的子树中有多少是x的前缀. 离线, 对AC自动机DFS一遍, 用dfs序+树状 ...

  3. bzoj 2434 [Noi2011]阿狸的打字机 AC自动机

    [Noi2011]阿狸的打字机 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 4001  Solved: 2198[Submit][Status][D ...

  4. BZOJ 2434: [Noi2011]阿狸的打字机 AC自动机+fail树+线段树

    Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的 ...

  5. bzoj 2434 [Noi2011]阿狸的打字机(fail树+离线处理+BIT)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2434 [题意] 按照一定规则生成n个字符串,回答若干个询问:(x,y),问第x个字符串 ...

  6. BZOJ 2434 [Noi2011]阿狸的打字机(AC自动机)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2434 [题目大意] 给出一个打印的过程,'a'-'z'表示输入字母,P表示打印该字符串 ...

  7. bzoj 2434 [Noi2011]阿狸的打字机——AC自动机

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2434 dfs AC自动机,走过的点权值+1,回溯的时候权值-1:走到询问的 y 串的节点,看 ...

  8. bzoj 2434: [Noi2011]阿狸的打字机

    #include<cstdio> #include<iostream> #include<cstring> #define M 100008 using names ...

  9. ●BZOJ 2434: [Noi2011]阿狸的打字机

    ●赘述题目 (题意就不赘述了) ●解法: ●我先想的一个比较暴力的方法(要TLE): (ac自动机)先求出last数组(参见刘汝佳的解释:last[j]:表示j节点沿着失配指针往回走时,遇到的下一个单 ...

随机推荐

  1. CF 96 D. Volleyball

    D. Volleyball http://codeforces.com/contest/96/problem/D 题意: n个路口,m条双向路,每条长度为w.每个路口有一个出租车司机,最多可以乘坐这辆 ...

  2. docker制作自己的镜像并上传dockerhub

    1.首先注册自己的dockerhub账号,注册地址:https://hub.docker.com 2.在linux服务器登录自己的账号:docker login --username=qiaoyeye ...

  3. 帮你理解学习lambda式

    概要     窗前明月光,疑是地上霜,举头望明月,低头思故乡.别误会这是开头诗与以下文章没任何关系. 今天我想给大家说道说道 C# lambda表达式,不废话,下面开始说道! lambda lambd ...

  4. C#与mongoDB初始环境搭建

    mongoDB官网https://www.mongodb.com/ mongoDB默认安装路径(Windows x64平台) C:\Program Files\MongoDB\Server\3.4\b ...

  5. 【UGUI】 (二)--------- 小地图

    在绝大多数游戏中,小地图都是极为常见的一个模块而且十分重要.在Unity里面如何制作一个地图其实也是比较简单的 一. 创建玩家与敌人 创建一个Capsule,命名为Player,代表我们的游戏玩家,创 ...

  6. object-fix/object-position

    今日浏览某大神的一篇博文时发现如下写法: .container > div > img { width: 100%; height: 100%; object-fit: cover; } ...

  7. 413. Reverse Integer【LintCode java】

    Description Reverse digits of an integer. Returns 0 when the reversed integer overflows (signed 32-b ...

  8. 【snmp】Linux开启snmp及查询

    1.Linux snmp 1.安装snmp yum install -y net-snmp* 2.备份snmp配置 cp /etc/snmp/snmpd.conf /etc/snmp/snmpd.co ...

  9. Python序列之字符串 (str)

    作者博文地址:http://www.cnblogs.com/spiritman/ Python字符串的常用操作包括以下但不限于以下操作: 字符串的替换.删除.切片.复制.连接.比较.查找.分割等 以下 ...

  10. Django 使用 Celery 实现异步任务

    对于网站来说,给用户一个较好的体验是很重要的事情,其中最重要的指标就是网站的浏览速度.因此服务端要从各个方面对网站性能进行优化,比如可采用CDN加载一些公共静态文件,如js和css:合并css或者js ...