首页 > 代码库 > Bzoj2434 [Noi2011]阿狸的打字机

Bzoj2434 [Noi2011]阿狸的打字机

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 2536  Solved: 1415

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

 

先把字符串建成AC自动机,然后对fail指针建立DFS序,利用DFS序来差分答案。

默默打开了hzw学长的博客,默默开抄。

  1 #include<iostream>  2 #include<cstdio>  3 #include<algorithm>  4 #include<cstring>  5 #include<queue>  6 #include<vector>  7 #define LL long long  8 using namespace std;  9 const int mxn=100010; 10 int read(){ 11     int x=0,f=1;char ch=getchar(); 12     while(ch<0 || ch>9){if(ch==-)f=-1;ch=getchar();} 13     while(ch>=0 && ch<=9){x=x*10+ch-0;ch=getchar();} 14     return x*f; 15 } 16 struct edge{int v,nxt;}e[mxn<<1]; 17 int hd[mxn],mct=0; 18 void add_edge(int u,int v){ 19     e[++mct].v=v;e[mct].nxt=hd[u];hd[u]=mct;return; 20 } 21 vector<int>ask[mxn];//询问 22 vector<int>id[mxn]; 23 int ans[mxn]; 24 // 25 int n,m; 26 char s[mxn]; 27 int ind[mxn],outd[mxn],sz=0; 28 int tr[mxn<<1]; 29 void add(int x,int v){while(x<=sz){tr[x]+=v;x+=x&-x;}} 30 int smm(int x){ 31     int res=0; 32     while(x){res+=tr[x];x-=x&-x;} 33     return res; 34 } 35 int pos[mxn],sct=0; 36 struct Aca{ 37     int t[mxn][26],fail[mxn]; 38     int fa[mxn]; 39     int rt,cnt; 40     void clear(){cnt=1;rt=1;for(int i=0;i<26;i++)t[0][i]=1;} 41     void insert(char s[]){ 42         int now=rt; 43         int len=strlen(s); 44         for(int i=0;i<len;i++){ 45             if(s[i]==P){pos[++sct]=now;continue;} 46             else if(s[i]==B){now=fa[now];continue;} 47             if(!t[now][s[i]-a]){ 48                 t[now][s[i]-a]=++cnt; 49                 fa[t[now][s[i]-a]]=now; 50             } 51             now=t[now][s[i]-a]; 52         } 53     } 54     void Build(){ 55         queue<int>q; 56         q.push(rt); 57         fail[1]=0; 58         while(!q.empty()){ 59             int now=q.front();q.pop(); 60             for(int i=0;i<26;i++){ 61                 if(t[now][i]){ 62                     int k=fail[now]; 63                     while(!t[k][i])k=fail[k]; 64                     fail[t[now][i]]=t[k][i]; 65                     q.push(t[now][i]); 66                 } 67             } 68         } 69     } 70 }aca; 71 void DFS(int u){ 72     ind[u]=++sz; 73     for(int i=hd[u];i;i=e[i].nxt){ 74         DFS(e[i].v); 75     } 76     outd[u]=++sz; 77     return; 78 } 79 int main() 80 { 81     int i,j,u,v; 82     scanf("%s",s); 83     n=strlen(s); 84     aca.clear(); 85     aca.insert(s); 86     aca.Build(); 87     for(int i=aca.rt;i<=aca.cnt;i++){ 88         add_edge(aca.fail[i],i); 89     } 90     DFS(0); 91     m=read(); 92     for(i=1;i<=m;i++){ 93         u=read();v=read(); 94         ask[v].push_back(u); 95         id[v].push_back(i); 96     } 97     int now=aca.rt;int t=0; 98     // 99     add(ind[1],1);//add(outd[1],-1);100     for(i=0;i<n;i++){101 //      printf("now: %c \n",s[i]);102         if(s[i]==P){103             t++;104             u=t;105             for(j=0;j<ask[u].size();j++){106                 v=pos[ask[u][j]];107 //              printf("%d to %d\n",ind[v],outd[v]);108 //              printf("%d %d\n",smm(outd[v]),smm(ind[v]-1));109                 ans[id[u][j]]=smm(outd[v])-smm(ind[v]-1);110             }111             continue;112         }113         else if(s[i]==B){114             add(ind[now],-1);//add(outd[now],1);115             now=aca.fa[now];continue;116         }117         now=aca.t[now][s[i]-a];118         add(ind[now],1);//add(outd[now],-1);119     }120     //121     for(i=1;i<=m;i++)printf("%d\n",ans[i]);122     return 0;123 }

 

Bzoj2434 [Noi2011]阿狸的打字机