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 }
生命中真正重要的不是你遭遇了什么,而是你记住了哪些事,又是如何铭记的。