记录编号 61628 评测结果 AAAAAAAAAA
题目名称 [NOI 2011]阿狸的打字机 最终得分 100
用户昵称 Gravatarcstdio 是否通过 通过
代码语言 C++ 运行时间 0.498 s
提交时间 2013-06-13 14:10:28 内存使用 36.36 MiB
显示代码纯文本
  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. #include<cmath>
  5. #include<iomanip>
  6. #include<vector>
  7. #include<queue>
  8. #include<cstring>
  9. using namespace std;
  10. const int SIZEN=200000,INF=0x7fffffff;
  11. class TTREE{//字典树
  12. public:
  13. char pos;
  14. int father;
  15. bool lea;//是否叶子
  16. int next[30];//next[i]存的是下一位'A'+i
  17. TTREE(){
  18. pos=father=lea=0;
  19. for(int i=0;i<30;i++) next[i]=0;
  20. }
  21. };
  22. TTREE tt[SIZEN];
  23. TTREE& root=tt[0];
  24. int tot=0;
  25. int M,N;
  26. string str;//输入的字串
  27. int pri[SIZEN]={0};//pri[i]表示第i个打印的字串对应的节点
  28. int nump=0;
  29. int fail[SIZEN]={0};//真・fail指针
  30. class FTREE{
  31. public:
  32. int father;
  33. vector<int> son;//子节点
  34. };
  35. FTREE ft[SIZEN];
  36. int dfn[SIZEN]={0};
  37. int low[SIZEN]={0},high[SIZEN]={0};
  38. bool visit[SIZEN]={0};
  39. int timer=1;
  40. void DFS(int x){
  41. if(visit[x]) return;
  42. visit[x]=true;
  43. dfn[x]=timer;
  44. low[x]=high[x]=timer;
  45. timer++;
  46. int i;
  47. for(i=0;i<ft[x].son.size();i++) DFS(ft[x].son[i]);
  48. low[ft[x].father]=min(low[ft[x].father],low[x]);
  49. high[ft[x].father]=max(high[ft[x].father],high[x]);
  50. }
  51. void addedge(int x,int y){//x指向y,x是父节点
  52. ft[x].son.push_back(y);
  53. ft[y].father=x;
  54. }
  55. void singlefail(int x){
  56. int ch=tt[x].pos-'a';
  57. int temp=fail[tt[x].father];
  58. while(temp!=0&&tt[temp].next[ch]==0){
  59. temp=fail[temp];
  60. }
  61. fail[x]=tt[temp].next[ch];
  62. addedge(tt[temp].next[ch],x);
  63. }
  64. void getfail(void){
  65. queue<int> Q;
  66. int i;
  67. fail[0]=0;
  68. for(i=0;i<26;i++){
  69. if(root.next[i]){
  70. Q.push(root.next[i]);
  71. fail[root.next[i]]=0;
  72. addedge(0,root.next[i]);
  73. }
  74. }
  75. int x;
  76. while(!Q.empty()){
  77. x=Q.front();Q.pop();
  78. for(i=0;i<26;i++){
  79. if(tt[x].next[i]!=0){
  80. singlefail(tt[x].next[i]);
  81. Q.push(tt[x].next[i]);
  82. }
  83. }
  84. }
  85. }
  86. void addson(int x,char ch){
  87. if(tt[x].next[ch-'a']) return;
  88. tt[x].next[ch-'a']=++tot;
  89. tt[tot].pos=ch;
  90. tt[tot].father=x;
  91. }
  92. void maketree(void){
  93. int i,temp;
  94. temp=0;//当前访问的节点
  95. for(i=0;i<str.size();i++){
  96. if(str[i]=='B') temp=tt[temp].father;
  97. else if(str[i]=='P') pri[++nump]=temp;
  98. else{
  99. addson(temp,str[i]);
  100. temp=tt[temp].next[str[i]-'a'];
  101. }
  102. }
  103. N=tot+1;
  104. for(i=0;i<=N;i++) low[i]=INF;
  105. }
  106. class REQ{
  107. public:
  108. int pos;
  109. int x,y;
  110. };
  111. REQ r[SIZEN];
  112. bool operator < (REQ a,REQ b){
  113. return a.y<b.y;
  114. }
  115. void read(void){
  116. cin>>str;
  117. cin>>M;
  118. int i;
  119. for(i=1;i<=M;i++){
  120. scanf("%d%d",&r[i].x,&r[i].y);
  121. r[i].pos=i;
  122. }
  123. sort(r+1,r+1+M);
  124. }
  125. int sum[SIZEN]={0};//真・树状数组
  126. int lowbit(int x){
  127. return x&(-x);
  128. }
  129. void change(int x,int num){
  130. while(x<=N){
  131. sum[x]+=num;
  132. x+=lowbit(x);
  133. }
  134. }
  135. int getsum(int x){
  136. int ans=0;
  137. while(x>0){
  138. ans+=sum[x];
  139. x-=lowbit(x);
  140. }
  141. return ans;
  142. }
  143. int ans[SIZEN]={0};
  144. void ask(void){
  145. int i,j=1,temp,nowp;
  146. temp=0;
  147. int nowr=r[1].y;
  148. nowp=0;
  149. char ch;
  150. for(i=0;i<str.size();i++){
  151. if(str[i]=='B'){
  152. change(dfn[temp],-1);
  153. temp=tt[temp].father;
  154. }
  155. else if(str[i]=='P'){
  156. nowp++;
  157. if(nowp==nowr){
  158. while(j<=M&&r[j].y==nowr){
  159. ans[r[j].pos]=getsum(high[pri[r[j].x]])-getsum(low[pri[r[j].x]]-1);
  160. j++;
  161. }
  162. if(j>M) break;
  163. nowr=r[j].y;
  164. }
  165. }
  166. else{
  167. ch=str[i];
  168. ch-='a';
  169. temp=tt[temp].next[(int)ch];
  170. change(dfn[temp],1);
  171. }
  172. }
  173. for(i=1;i<=M;i++) printf("%d\n",ans[i]);
  174. }
  175. int main(){
  176. freopen("noi2011_type.in","r",stdin);
  177. freopen("noi2011_type.out","w",stdout);
  178. read();
  179. maketree();
  180. getfail();
  181. DFS(0);
  182. ask();
  183. return 0;
  184. }