BZOJ 2434 [NOI2011]阿狸的打字机
题面:
2434: [Noi2011]阿狸的打字机
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 3261 Solved: 1795
[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
3
1 2
1 3
2 3
Sample Output
2
1
0
1
0
HINT
1<=N<=10^5
1<=M<=10^5
输入总长<=10^5
如果对于每次询问都暴力查询肯定会TLE(废话!)。
我们可以建出fail树(将fail指针反向),那么串x在串y中出现次数就是代表y的节点到根的路径上,
在x的fai子树中节点的个数(可以画图归纳得出)。然后就用DFS序和树状数组离线处理。
1 #include<iostream> 2 #include<stdio.h> 3 #include<string.h> 4 #include<vector> 5 using namespace std; 6 #define maxn 100001 7 int n,m; 8 int haha[maxn]; 9 int read() 10 { 11 char s=getchar(); 12 int a=0; 13 while(s<'0'||s>'9') 14 s=getchar(); 15 while(s>='0'&&s<='9') 16 { 17 a=a*10+s-'0'; 18 s=getchar(); 19 } 20 return a; 21 } 22 class fenwick_tree 23 { 24 private: 25 #define lowbit(x) x&(-x) 26 int c[maxn]; 27 public: 28 fenwick_tree() 29 { 30 memset(c,0,sizeof(c)); 31 } 32 inline void update(int x,int w) 33 { 34 for(;x<=n;x+=lowbit(x))c[x]+=w; 35 } 36 inline int query(int x) 37 { 38 int ans=0; 39 for(;x>0;x-=lowbit(x))ans+=c[x]; 40 return ans; 41 } 42 }bit; 43 class AC_auto 44 { 45 public: 46 struct node 47 { 48 int id,flag,l,r; 49 node *son[26],*fa,*fail; 50 }*root,tree[maxn],*q[maxn],*print[maxn]; 51 int indx,head,tail,cnt,num; 52 struct edge 53 { 54 node *u,*v; 55 int nex; 56 }edges[maxn]; 57 int nxt[maxn],edge_cnt,dfn; 58 node *newnode(int id,node *f) 59 { 60 node *t;t=&tree[indx++]; 61 t->id=id;t->fa=f;t->fail=NULL; 62 for(int i=0;i<26;i++)t->son[i]=NULL; 63 return t; 64 } 65 AC_auto() 66 { 67 edge_cnt=0; 68 memset(nxt,0,sizeof(nxt)); 69 cnt=0;num=0;dfn=0; 70 indx=0;head=1;tail=0; 71 root=newnode(0,NULL); 72 } 73 void insert(char *key) 74 { 75 node *t=root;char *p=key; 76 77 while(*p) 78 { 79 if(*p=='P') 80 { 81 t->flag=++cnt;print[cnt]=t; 82 } 83 else 84 if(*p=='B')t=t->fa; 85 else 86 { 87 if(!t->son[*p-'a']) 88 t->son[*p-'a']=newnode(++num,t); 89 t=t->son[*p-'a']; 90 } 91 ++p; 92 } 93 } 94 void bfs() 95 { 96 node *t,*p;q[++tail]=root; 97 while(head<=tail) 98 { 99 t=q[head++]; 100 for(int i=0;i<26;i++) 101 if(t->son[i]) 102 { 103 p=t->fail; 104 while(p&&!p->son[i])p=p->fail; 105 t->son[i]->fail=p?p->son[i]:root; 106 q[++tail]=t->son[i]; 107 } 108 } 109 } 110 void add(node *u,node *v) 111 { 112 edges[++edge_cnt]=(edge){u,v,nxt[u->id]}; 113 nxt[u->id]=edge_cnt; 114 } 115 void build_failtree(node *t) 116 { 117 for(int i=0;i<26;i++) 118 if(t->son[i]) 119 { 120 add(t->son[i]->fail,t->son[i]);build_failtree(t->son[i]); 121 } 122 } 123 void dfs(node *t) 124 { 125 t->l=++dfn; 126 for(int i=nxt[t->id];i;i=edges[i].nex) 127 if(edges[i].v!=NULL) 128 dfs(edges[i].v); 129 t->r=dfn; 130 } 131 struct QAQ 132 { 133 int id;node *t; 134 }; 135 vector<QAQ>QWQ[maxn]; 136 void work(node *t) 137 { 138 bit.update(t->l,1); 139 int s=QWQ[t->id].size(); 140 QAQ ss; 141 for(int i=0;i<s;i++) 142 { 143 ss=QWQ[t->id][i]; 144 haha[ss.id]=bit.query(ss.t->r)-bit.query(ss.t->l-1); 145 } 146 for(int i=0;i<26;i++) 147 if(t->son[i]!=NULL) 148 work(t->son[i]); 149 bit.update(t->l,-1); 150 } 151 }ac_auto; 152 char s[maxn]; 153 int main() 154 { 155 int x,y; 156 scanf("%s",s); 157 n=strlen(s); 158 ac_auto.insert(s); 159 ac_auto.bfs(); 160 ac_auto.build_failtree(ac_auto.root); 161 ac_auto.dfs(ac_auto.root); 162 scanf("%d",&m); 163 for(int i=1;i<=m;i++) 164 { 165 scanf("%d%d",&x,&y); 166 ac_auto.QWQ[ac_auto.print[y]->id].push_back((AC_auto::QAQ){i,ac_auto.print[x]}); 167 } 168 ac_auto.work(ac_auto.root); 169 for(int i=1;i<=m;i++) 170 printf("%d\n",haha[i]); 171 }