码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2017-05-30 16:16:25      阅读:189      评论:0      收藏:0      [点我收藏+]

标签:scanf   ring   span   功能   stat   void   line   整数   turn   

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2434

[Noi2011]阿狸的打字机

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 3150  Solved: 1737
[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

fail树+树状数组离线,挺好的题。

  1 #include<cstdio>
  2 #include<cstring>
  3 const int maxn = 200005;
  4 char str[maxn];
  5 int n,m;
  6 int a[maxn][29],point[maxn],fa[maxn],q[maxn],sz=1;
  7 int pos[maxn];
  8  
  9 void ins(){
 10     int now=1,id=0;
 11     n=strlen(str);
 12     for(int i=0;i<n;i++){
 13         if(str[i]==P){
 14             pos[++id]=now;
 15             continue;
 16         }else if(str[i]==B){
 17             now=fa[now];
 18             continue;
 19         }
 20         else{
 21             int k=str[i]-a+1;
 22             if(a[now][k]){
 23                 fa[a[now][k]]=now;
 24                 now=a[now][k];
 25             }else{
 26                 a[now][k]=++sz;
 27                 fa[a[now][k]]=now;
 28                 now=a[now][k];
 29             }
 30         }
 31     }
 32 }
 33 void acm(){
 34     for(int i=1;i<=27;i++)a[0][i]=1;
 35     int l=0,r=0;
 36     q[r++]=1;point[1]=0;
 37     while(l<r){
 38         int now=q[l++];
 39         for(int i=1;i<=27;i++){
 40             if(!a[now][i])continue;
 41             int k=point[now];
 42             while(!a[k][i])k=point[k];
 43             point[a[now][i]]=a[k][i];
 44             q[r++]=a[now][i];
 45         }
 46     }
 47 }
 48 int h[maxn],nx[maxn<<1],to[maxn<<1],cnt;
 49 void add_edge(int u,int v){
 50     to[++cnt]=v;nx[cnt]=h[u];h[u]=cnt;
 51 }
 52 void link(int u,int v){
 53     add_edge(u,v);add_edge(v,u);
 54 }
 55 void build_fail(){
 56     for(int i=1;i<=sz;i++){
 57         link(i,point[i]);
 58     }
 59 }
 60 int hq[maxn],nxq[maxn<<1],toq[maxn<<1],cntq;
 61 int l[maxn],r[maxn],dfs_clock,dfn[maxn];
 62 void add_edgeq(int u,int v){
 63     toq[++cntq]=v;nxq[cntq]=hq[u];hq[u]=cntq;
 64 }
 65 void dfs(int x,int pr){
 66 //  printf("%d %d\n",x,dfs_clock);
 67 //  dfn[++dfs_clock]=x;
 68     l[x]=++dfs_clock;
 69     for(int i=h[x];i;i=nx[i]){
 70         if(to[i]==pr)continue;
 71         dfs(to[i],x);
 72     }
 73     r[x]=++dfs_clock;
 74 }
 75 int fenwick[maxn];
 76 void add(int x,int delta){
 77     while(x<=dfs_clock){
 78         fenwick[x]+=delta;
 79         x+=(x&(-x));
 80     }
 81 }
 82 int sum(int x){
 83     int rt=0;
 84     while(x){
 85         rt+=fenwick[x];
 86         x-=(x&(-x));
 87     }
 88     return rt;
 89 }
 90 int ans[maxn];
 91 void solve(){
 92     int now=1,id=0;
 93     add(l[1],1);
 94     for(int i=0;i<n;i++){
 95         if(str[i]==P){
 96             id++;
 97             for(int x=hq[id];x;x=nxq[x]){
 98                 int t=pos[toq[x]];
 99                 ans[x]=sum(r[t])-sum(l[t]-1);
100             }
101         }else if(str[i]==B){
102             add(l[now],-1);now=fa[now];
103         }
104         else{
105             now=a[now][str[i]-a+1];
106             add(l[now],1);
107         }
108     }
109 }
110 int main(){
111     scanf("%s",str);
112     ins();
113     acm();
114     build_fail();
115     dfs(0,0);
116      
117     scanf("%d",&m);
118     for(int i=1;i<=m;i++){
119         int _a,_b;
120         scanf("%d%d",&_a,&_b);
121         add_edgeq(_b,_a);
122     }
123     solve();
124     for(int i=1;i<=m;i++)printf("%d\n",ans[i]);
125     return 0;
126  
127 }
128 

 

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

标签:scanf   ring   span   功能   stat   void   line   整数   turn   

原文地址:http://www.cnblogs.com/kvrmnks/p/6919878.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!