首页 > 代码库 > BZOJ 2434 [NOI2011]阿狸的打字机

BZOJ 2434 [NOI2011]阿狸的打字机

题面:

2434: [Noi2011]阿狸的打字机

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

Sample Output

2
1
0

HINT

 1<=N<=10^5

1<=M<=10^5

输入总长<=10^5

Source

Trie

如果对于每次询问都暴力查询肯定会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 }
BZOJ 2434

 

BZOJ 2434 [NOI2011]阿狸的打字机