BZOJ2434: [Noi2011]阿狸的打字机

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
 
这道题看上去很迷啊。。。
考虑各种字符串做法,这是多模匹配,那就AC机树上硬搞
想想AC机fail指针定义:是根节点到该节点组成字符串的后缀
考虑从y串往上跳,构造出一颗后缀树,发现:
答案是x子树中有多少个y串中的节点,这可以用树状数组优化
那么就一个一个y串搞,排序下,然后再访问一下给出的打字顺序即可
代码如下:
//MT_LI
#include<cmath> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> using namespace std; struct AC_machine { int son[31],fail,fa; AC_machine(){fail=0;memset(son,-1,sizeof(son));} }t[210000]; int cnt,root,s[210000]; int list[210000]; int l[210000],r[210000],id; int cc[210000]; int lowbit(int x){return x&-x;} void change(int x,int d){while(x<=id)cc[x]+=d,x+=lowbit(x);} int getsum(int x){int sum=0;while(x)sum+=cc[x],x-=lowbit(x);return sum;} int n;char st[210000]; struct node{ int x,y,next; }a[210000];int len,last[210000]; void ins(int x,int y) { len++; a[len].x=x;a[len].y=y; a[len].next=last[x];last[x]=len; } void init() { scanf("%s",st+1);int slen=strlen(st+1); root=0;cnt=0;n=0;int now=root; for(int i=1;i<=slen;i++) { if(st[i]=='B')now=t[now].fa; else if(st[i]=='P')s[++n]=now; else { int y=st[i]-'a'+1; if(t[now].son[y]==-1)t[now].son[y]=++cnt,t[t[now].son[y]].fa=now; now=t[now].son[y]; } } } void dfs(int x) { l[x]=++id; for(int k=last[x];k;k=a[k].next) { int y=a[k].y; dfs(y); } r[x]=id; } void bfs() { int head=1,tail=2; list[1]=0; while(head!=tail) { int x=list[head]; for(int i=1;i<=26;i++) { int y=t[x].son[i]; if(y!=-1) { if(x==root)t[y].fail=0; else { int p=t[x].fail; while(p!=root&&t[p].son[i]==-1)p=t[p].fail; t[y].fail=t[p].son[i]; } list[tail++]=y; } } head++; } len=0;memset(last,0,sizeof(last)); for(int i=1;i<=cnt;i++)ins(t[i].fail,i); id=0;dfs(root); } struct Q{ int x,y,id; }q[210000]; bool cmp(Q a,Q b){return a.y<b.y;} int ans[210000]; int main() { init(); bfs(); int m; scanf("%d",&m); for(int i=1;i<=m;i++)scanf("%d%d",&q[i].x,&q[i].y),q[i].id=i; sort(q+1,q+1+m,cmp); int pos=1;int num=0,now=root; int slen=strlen(st+1); for(int i=1;i<=slen;i++) { if(st[i]=='P') { num++; while(q[pos].y==num) { int u=s[q[pos].x]; ans[q[pos].id]=getsum(r[u])-getsum(l[u]-1); pos++; } } else { if(st[i]=='B')change(l[now],-1),now=t[now].fa; else now=t[now].son[st[i]-'a'+1],change(l[now],1); } } for(int i=1;i<=m;i++)printf("%d\n",ans[i]); return 0; }

 

posted @ 2018-10-08 19:06  MT_LI  阅读(107)  评论(0编辑  收藏  举报