[bzoj2434] [Noi2011]阿狸的打字机

  AC自动机+树状数组。

  先把fail边反向建出fail树来。。

  第x个字符串在第y个字符串中出现了多少次。对于y的每个前缀,如果它结尾可以通过fail跳到x的结尾的话,那么就出现了x。。

  也就是查询x的fail子树中,有多少个y的节点。

  在trie上暴力跑,在树状数组上加入根到当前节点路径上的点(将对应dfn值所在的地方+1),

  跑到y的结束节点时,对于每个对应的查询x,求出x的子树中有多少个点就行了。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define ll long long
 6 using namespace std;
 7 const int maxn=100233;
 8 struct zs{int too,pre;}e[maxn],e1[maxn];int tot,last[maxn],tot1,last1[maxn];
 9 int too[maxn],pre[maxn],id[maxn],la[maxn],tt;
10 int L[maxn],R[maxn],ed[maxn],tim;
11 int t[maxn];
12 int fail[maxn],ch[maxn][26],dl[maxn],fa[maxn];
13 int i,j,k,n,m,cnt,node;
14 int ans[maxn];
15 char s[maxn];
16  
17 int ra;char rx;
18 inline int read(){
19     rx=getchar(),ra=0;
20     while(rx<'0'||rx>'9')rx=getchar();
21     while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra;
22 }
23 inline void insert(int a,int b){e[++tot].too=b,e[tot].pre=last[a],last[a]=tot;}
24 inline void getfail(){
25     int l=0,r=1,i,now,p;dl[1]=0;
26     while(l<r){
27         now=dl[++l];
28         for(i=0;i<26;i++)if(ch[now][i]){
29             dl[++r]=ch[now][i];
30             for(p=fail[now];p&&!ch[p][i];p=fail[p]);
31             fail[ch[now][i]]=!now?0:ch[p][i],insert(fail[ch[now][i]],ch[now][i]);
32         }
33     }
34 }
35 void dfs(int x){
36     L[x]=++tim;
37     for(int i=last[x];i;i=e[i].pre)dfs(e[i].too);
38     R[x]=tim;
39 }
40 inline void ins(int a,int b){too[++tt]=b,id[tt]=i,pre[tt]=la[a],la[a]=tt;}
41 inline void insgg(int a,int b){e1[++tot1].too=b,e1[tot1].pre=last1[a],last1[a]=tot1;}
42  
43 inline void add(int x){while(x<=node)t[x]++,x+=x&-x;}
44 inline void del(int x){while(x<=node)t[x]--,x+=x&-x;}
45 inline int query(int l,int r){
46     int sm=0;l--;
47     while(r)sm+=t[r],r-=r&-r;
48     while(l)sm-=t[l],l-=l&-l;return sm;
49 }
50 void dfs2(int x){
51     int i,x1,y,j;//printf("in:   %d\n",x);
52     if(x)add(L[x]);
53     for(i=last1[x];i;i=e1[i].pre)
54         for(y=e1[i].too,j=la[y];j;j=pre[j])
55             x1=too[j],ans[id[j]]=query(L[ed[x1]],R[ed[x1]]);
56     for(i=0;i<26;i++)if(ch[x][i])/*printf("%d-->%d\n",x,ch[x][i]),*/dfs2(ch[x][i]);
57 //  printf("out:   %d\n",x);
58     if(x)del(L[x]);
59 }
60 int main(){
61     scanf("%s",s+1),n=strlen(s+1);
62     int now=0;
63     for(i=1;i<=n;i++){
64         if(s[i]=='P')cnt++,ed[cnt]=now,insgg(now,cnt);else
65         if(s[i]=='B')now=fa[now];else
66         if(!ch[now][s[i]-'a'])ch[now][s[i]-'a']=++node,fa[node]=now,now=node;
67         else now=ch[now][s[i]-'a'];
68     }node++;
69     getfail();
70     dfs(0);
71     m=read();
72     for(i=1;i<=m;i++)ins(read(),read());
73     dfs2(0);
74     for(i=1;i<=m;i++)printf("%d\n",ans[i]);
75 }
View Code

 

posted @ 2016-06-28 14:07  czllgzmzl  阅读(207)  评论(0编辑  收藏  举报