AC自动机:BZOJ 2434 阿狸的打字机
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AC自动机:BZOJ 2434 阿狸的打字机相关的知识,希望对你有一定的参考价值。
2434: [Noi2011]阿狸的打字机
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1834 Solved: 1053
[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
3
1 2
1 3
2 3
Sample Output
1
0
HINT
1<=N<=10^5
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <queue> 5 #include <algorithm> 6 using namespace std; 7 const int maxn=1e5+10; 8 char S[maxn]; 9 int Query[maxn][2],ans[maxn],cntQ; 10 struct A_Cautomation{ 11 int ch[maxn][27],fail[maxn],end[maxn],fa[maxn],ID[maxn],cnt,root,cont; 12 int fir[maxn],nxt[maxn],to[maxn],cot; 13 int be[maxn],en[maxn],sjc; 14 void Init() 15 { 16 memset(ch,0,sizeof(ch)); 17 memset(fail,0,sizeof(fail)); 18 memset(end,0,sizeof(end)); 19 sjc=cot=cnt=cont=root=0; 20 } 21 void Insert() 22 { 23 scanf("%s",S); 24 int len=strlen(S),node=root; 25 for(int i=0;i<len;i++) 26 { 27 if(S[i]>=‘a‘&&S[i]<=‘z‘){ 28 if(ch[node][S[i]-‘`‘]){ 29 node=ch[node][S[i]-‘`‘]; 30 } 31 else{ 32 fa[++cnt]=node; 33 node=ch[node][S[i]-‘`‘]=cnt; 34 } 35 } 36 else{ 37 if(S[i]==‘B‘){ 38 node=fa[node]; 39 } 40 else{ 41 end[node]=++cont; 42 ID[cont]=node; 43 } 44 } 45 } 46 } 47 void Build() 48 { 49 queue<int>q; 50 for(int i=1;i<=26;i++){ 51 if(ch[root][i]){ 52 fail[ch[root][i]]=root; 53 q.push(ch[root][i]); 54 } 55 else 56 ch[root][i]=root; 57 } 58 while(!q.empty()) 59 { 60 int node=q.front();q.pop(); 61 for(int i=1;i<=26;i++){ 62 if(ch[node][i]){ 63 fail[ch[node][i]]=ch[fail[node]][i]; 64 q.push(ch[node][i]); 65 } 66 else{ 67 ch[node][i]=ch[fail[node]][i]; 68 } 69 } 70 } 71 } 72 73 void addedge(int a,int b) 74 {nxt[++cot]=fir[a];fir[a]=cot;to[cot]=b;} 75 76 void DFS(int node) 77 { 78 be[node]=++sjc; 79 for(int i=fir[node];i;i=nxt[i]) 80 DFS(to[i]); 81 en[node]=sjc; 82 } 83 84 void BuildTree() 85 { 86 for(int i=1;i<=cnt;i++) 87 addedge(fail[i],i); 88 89 DFS(root); 90 } 91 92 int bit[maxn]; 93 void change(int k,int x) 94 { 95 while(k<=100000) 96 { 97 bit[k]+=x; 98 k+=k&(-k); 99 } 100 } 101 102 int Quer(int k) 103 { 104 int ret=0; 105 while(k) 106 { 107 ret+=bit[k]; 108 k-=k&(-k); 109 } 110 return ret; 111 } 112 113 void Solve() 114 { 115 memset(fir,0,sizeof(fir));cot=0; 116 memset(bit,0,sizeof(bit)); 117 for(int i=1;i<=cntQ;i++) 118 Query[i][0]=ID[Query[i][0]], 119 Query[i][1]=ID[Query[i][1]], 120 addedge(Query[i][1],Query[i][0]); 121 122 int len=strlen(S),node=root; 123 for(int i=0;i<len;i++) 124 { 125 if(S[i]>=‘a‘&&S[i]<=‘z‘){ 126 node=ch[node][S[i]-‘`‘]; 127 change(be[node],1); 128 } 129 else{ 130 if(S[i]==‘B‘){ 131 change(be[node],-1); 132 node=fa[node]; 133 } 134 else{ 135 for(int i=fir[node];i;i=nxt[i]){ 136 ans[i]=Quer(en[to[i]])-Quer(be[to[i]]-1); 137 } 138 } 139 } 140 } 141 142 for(int i=1;i<=cntQ;i++) 143 printf("%d\n",ans[i]); 144 } 145 }AC; 146 147 int main() 148 { 149 AC.Init(); 150 AC.Insert(); 151 AC.Build(); 152 AC.BuildTree(); 153 154 int Q; 155 scanf("%d",&Q); 156 while(Q--) 157 scanf("%d%d",&Query[cntQ][0],&Query[++cntQ][1]); 158 159 AC.Solve(); 160 return 0; 161 }
以上是关于AC自动机:BZOJ 2434 阿狸的打字机的主要内容,如果未能解决你的问题,请参考以下文章
AC日记——[Noi2011]阿狸的打字机 bzoj 2434
bzoj2434: [Noi2011]阿狸的打字机 字符串-AC自动机-BIT
BZOJ 2434 [Noi2011]阿狸的打字机(AC自动机)