您的位置:首页 > 其它

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

2016-06-28 14:07 489 查看
  AC自动机+树状数组。

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

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

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

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

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

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=100233;
struct zs{int too,pre;}e[maxn],e1[maxn];int tot,last[maxn],tot1,last1[maxn];
int too[maxn],pre[maxn],id[maxn],la[maxn],tt;
int L[maxn],R[maxn],ed[maxn],tim;
int t[maxn];
int fail[maxn],ch[maxn][26],dl[maxn],fa[maxn];
int i,j,k,n,m,cnt,node;
int ans[maxn];
char s[maxn];

int ra;char rx;
inline int read(){
rx=getchar(),ra=0;
while(rx<'0'||rx>'9')rx=getchar();
while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra;
}
inline void insert(int a,int b){e[++tot].too=b,e[tot].pre=last[a],last[a]=tot;}
inline void getfail(){
int l=0,r=1,i,now,p;dl[1]=0;
while(l<r){
now=dl[++l];
for(i=0;i<26;i++)if(ch[now][i]){
dl[++r]=ch[now][i];
for(p=fail[now];p&&!ch[p][i];p=fail[p]);
fail[ch[now][i]]=!now?0:ch[p][i],insert(fail[ch[now][i]],ch[now][i]);
}
}
}
void dfs(int x){
L[x]=++tim;
for(int i=last[x];i;i=e[i].pre)dfs(e[i].too);
R[x]=tim;
}
inline void ins(int a,int b){too[++tt]=b,id[tt]=i,pre[tt]=la[a],la[a]=tt;}
inline void insgg(int a,int b){e1[++tot1].too=b,e1[tot1].pre=last1[a],last1[a]=tot1;}

inline void add(int x){while(x<=node)t[x]++,x+=x&-x;}
inline void del(int x){while(x<=node)t[x]--,x+=x&-x;}
inline int query(int l,int r){
int sm=0;l--;
while(r)sm+=t[r],r-=r&-r;
while(l)sm-=t[l],l-=l&-l;return sm;
}
void dfs2(int x){
int i,x1,y,j;//printf("in:   %d\n",x);
if(x)add(L[x]);
for(i=last1[x];i;i=e1[i].pre)
for(y=e1[i].too,j=la[y];j;j=pre[j])
x1=too[j],ans[id[j]]=query(L[ed[x1]],R[ed[x1]]);
for(i=0;i<26;i++)if(ch[x][i])/*printf("%d-->%d\n",x,ch[x][i]),*/dfs2(ch[x][i]);
//  printf("out:   %d\n",x);
if(x)del(L[x]);
}
int main(){
scanf("%s",s+1),n=strlen(s+1);
int now=0;
for(i=1;i<=n;i++){
if(s[i]=='P')cnt++,ed[cnt]=now,insgg(now,cnt);else
if(s[i]=='B')now=fa[now];else
if(!ch[now][s[i]-'a'])ch[now][s[i]-'a']=++node,fa[node]=now,now=node;
else now=ch[now][s[i]-'a'];
}node++;
getfail();
dfs(0);
m=read();
for(i=1;i<=m;i++)ins(read(),read());
dfs2(0);
for(i=1;i<=m;i++)printf("%d\n",ans[i]);
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: