BZOJ 2434 阿狸的打字机

Posted zhangenming

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 2434 阿狸的打字机相关的知识,希望对你有一定的参考价值。

2434: [Noi2011]阿狸的打字机

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 3593  Solved: 1952
[Submit][Status][Discuss]

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

 

Source

Trie

摘抄自cydiater大神

这个如果真的不会玩用KMP打暴力很好想到。好吧其实不应该向kmp方面想,这个多字符串匹配显然是AC自动机。给出的字符串就是给你模拟了建立Trie树的过程。然后考虑根据每个点的fail指针建立fail树。

stristrj里出现了几次。显然就是问在Trie树里,有多少个strj的元素指向stri,在fail树里就转化成了在stri的末尾元素所形成子树里有多少个strj的元素。如果在线求这个就太麻烦了。

我们用树状数组离线搞。

再回到给出的那个字符串,其实那就是一个访问路径。首先在fail树上跑一遍dfs,求出来每个节点的入栈时间和出栈时间。然后按照字符串这个路径访问整个Trie树,每进入一个节点,把这个节点之前进栈的权值全部+1,每退出一个节点,把这个节点之前进栈的权值全部-1。每次访问到存在询问的节点。把进栈和出栈之间的权值累加就行了。

技术分享图片
  1 # include <bits/stdc++.h>
  2 using namespace std;
  3 inline int read(){
  4   int x=0;int f=1;char ch=getchar();
  5   if(!isdigit(ch)) {if(ch==-) f=-1;ch=getchar();}
  6   while(isdigit(ch)) {x=x*10+ch-0;ch=getchar();}
  7   return x*f;
  8 } 
  9 const int MAXN=1e6+10; 
 10 namespace zhangenming{
 11     struct node{
 12         int y,next;
 13     }e[MAXN];
 14     int linkk[MAXN<<1],cnt,next[MAXN][30],fa[MAXN],n,m,ans[MAXN],c[MAXN]={};
 15     int strl,id[MAXN],dfs_clock=0,op=0,din[MAXN],dout[MAXN],len=0,now=0,fail[MAXN];
 16     inline int lowbit(int x){
 17         return x&-x;
 18     }
 19     void add(int x,int val){
 20         while(x<=MAXN){
 21             c[x]+=val;
 22             x+=lowbit(x);
 23         }
 24     }
 25     int get(int x){
 26      int sum=0;
 27      while(x>0){
 28          sum+=c[x];
 29          x-=lowbit(x);
 30      }    
 31      return sum;
 32     }
 33     string str;
 34     inline void insert(int xx,int yy){
 35         e[++len].y=yy;e[len].next=linkk[xx];linkk[xx]=len;
 36     }
 37     void init(){
 38         cin>>str;n=read();
 39         strl=str.size();
 40         for(int i=1;i<=n;i++){
 41             int xx=read()+strl;
 42             int yy=read()+strl;
 43             insert(yy,xx);
 44         }
 45     } 
 46     void build_ac(){
 47         now=0;
 48         for(int i=0;i<strl;i++){
 49             if(str[i]==B){
 50                 now=fa[now];
 51                 //cout<<now<<endl;
 52             }
 53             else if(str[i]==P){
 54                 id[++op]=now;
 55                 //cout<<now<<endl;
 56             }
 57             else{
 58                 if(!next[now][str[i]-a]) next[now][str[i]-a]=++cnt;
 59                 fa[next[now][str[i]-a]]=now;
 60                 now=next[now][str[i]-a];
 61             }
 62         }
 63     }
 64     int q[MAXN<<1];
 65     void build_fail(){
 66         int head=-0;int tail=0;
 67         for(int i=0;i<=25;i++){
 68             if(next[0][i]) q[++tail]=next[0][i];
 69         }
 70         while(head<tail){
 71         int tn=q[++head];
 72         for(int i=0;i<=25;i++){
 73             int son=next[tn][i];
 74             if(!son) next[tn][i]=next[fail[tn]][i];
 75             else {
 76                 fail[son]=next[fail[tn]][i];
 77                 q[++tail]=son;
 78             }
 79         }    
 80       }
 81       for(int i=1;i<=cnt;i++){
 82           insert(fail[i],i);
 83       }
 84     }
 85     void dfs(int st){
 86      din[st]=++dfs_clock;
 87      for(int i=linkk[st];i;i=e[i].next){
 88          dfs(e[i].y);
 89      }    
 90      dout[st]=++dfs_clock;
 91     }
 92     void solve(){
 93         build_ac();build_fail();
 94         dfs(0);
 95         cnt=0;now=0;
 96         for(int i=0;i<strl;i++){
 97             if(str[i]==B){
 98                 add(din[now],-1);now=fa[now];
 99                 
100             }
101             else if(str[i]==P){
102                 cnt++;
103                 for(int j=linkk[cnt+strl];j;j=e[j].next){
104                     int y=id[e[j].y-strl];
105                     ans[j]=get(dout[y])-get(din[y]-1);
106                 }
107             }
108             else{
109                 now=next[now][str[i]-a];
110                 add(din[now],1);
111             }
112         }
113     }
114     void print(){
115         for(int i=1;i<=n;i++){
116             printf("%d\n",ans[i]);
117         }
118     }
119 }
120 int main(){
121     using namespace zhangenming;
122     init();
123     solve();
124     print();
125     return 0;
126 }
代码

 











































以上是关于BZOJ 2434 阿狸的打字机的主要内容,如果未能解决你的问题,请参考以下文章

bzoj2434NOI2011阿狸的打字机

BZOJ 2434 [NOI2011]阿狸的打字机

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

[bzoj 2434][Noi2011]阿狸的打字机

AC自动机:BZOJ 2434 阿狸的打字机

BZOJ 2434 阿狸的打字机