BZOJ2434 NOI2011阿狸的打字机

询问x这个串在y中出现的次数。

fail数组有一个性质就是一旦a的fail指向b那么b所代表的字串一定是a的后缀。

所以我们看fail树(即按fail反向建树)中x的子树有多少y的结点即可。

这个操作可以使用树状数组维护dfs序操作。

By:大奕哥

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 const int N=1e5+10;
  4 int head[N],dead[N],cnt,ent,dnt,num,n,m,idx,fa[N],pos[N],l[N],r[N];
  5 char s[N];
  6 queue<int>q;
  7 struct poin{
  8     int v[26],f,s;
  9 }t[N<<1];
 10 struct node{
 11     int to,nex;
 12 }e[N];
 13 struct edge{
 14     int to,nex;
 15 }d[N];
 16 void add(int x,int y)
 17 {
 18     e[++ent].to=y;e[ent].nex=head[x];head[x]=ent;
 19 }
 20 void add2(int x,int y)
 21 {
 22     d[++dnt].to=y;d[dnt].nex=dead[x];dead[x]=dnt;
 23 }
 24 int tr[N<<1];
 25 inline int lowbit(int x){return x&(-x);}
 26 int query(int x)
 27 {
 28     int ans=0;
 29     for(;x;x-=lowbit(x))ans+=tr[x];
 30     return ans;
 31 }
 32 void update(int x,int w)
 33 {
 34     for(;x<=idx;x+=lowbit(x))tr[x]+=w;
 35 }
 36 void build()
 37 {
 38     int now=0;
 39     for(int i=0;i<n;++i)
 40     {
 41         if(s[i]=='P')pos[++num]=now;
 42         else if(s[i]=='B')now=fa[now];
 43         else{
 44             if(!t[now].v[s[i]-'a'])
 45                 t[now].v[s[i]-'a']=++cnt;
 46             fa[t[now].v[s[i]-'a']]=now;
 47             now=t[now].v[s[i]-'a'];
 48         }
 49     }
 50     return;
 51 }
 52 void getfail()
 53 {
 54     for(int i=0;i<26;++i)
 55     {
 56         if(t[0].v[i])
 57         q.push(t[0].v[i]),t[t[0].v[i]].f=0;
 58     }
 59     while(!q.empty())
 60     {
 61         int x=q.front();q.pop();
 62         for(int i=0;i<26;++i)
 63         {
 64             if(t[x].v[i])
 65             {
 66                 t[t[x].v[i]].f=t[t[x].f].v[i];
 67                 q.push(t[x].v[i]);
 68             }
 69             else{
 70                 t[x].v[i]=t[t[x].f].v[i];
 71             }
 72         }
 73     }
 74     return;
 75 }
 76 void maketree()
 77 {
 78     for(int i=1;i<=cnt;++i)
 79     {
 80         int x=t[i].f;int y=i;
 81         add(x,y);
 82     }
 83     return;
 84 }
 85 void dfs(int x)
 86 {
 87     l[x]=++idx;
 88     for(int i=head[x];i;i=e[i].nex)
 89     {
 90         int y=e[i].to;
 91         dfs(y);
 92     }
 93     r[x]=++idx;
 94     return;
 95 }
 96 int ans[N];
 97 void work()
 98 {
 99     scanf("%d",&m);int id;int x,y;
100     for(int i=1;i<=m;++i)
101     {
102         scanf("%d%d",&x,&y);add2(y,x);
103     }int now=0;
104     for(int i=0;i<n;++i)
105     {
106         if(s[i]=='B')
107         {
108             update(l[now],-1);now=fa[now];
109         }
110         else if(s[i]=='P')
111         {
112             ++id;
113             for(int j=dead[id];j;j=d[j].nex)
114             {
115                 int y=pos[d[j].to];
116                 ans[j]=query(r[y])-query(l[y]-1);
117             }
118         }
119         else
120         {
121             now=t[now].v[s[i]-'a'];
122             update(l[now],1);
123         }
124     }
125     for(int i=1;i<=m;++i)
126     printf("%d\n",ans[i]);
127     return;
128 }
129 int main()
130 {
131     scanf("%s",s);
132     n=strlen(s);
133     build();
134     getfail();
135     maketree();
136     dfs(0);
137     work();
138     return 0;
139 }

 

posted @ 2018-01-22 14:30  大奕哥&VANE  阅读(147)  评论(0编辑  收藏  举报