您的位置:首页 > 其它

bzoj 2434: [Noi2011]阿狸的打字机

2016-03-21 23:20 141 查看
#include<cstdio>
#include<iostream>
#include<cstring>
#define M 100008
using namespace std;
char ch[M];
int cnt=1,pos[M],now,fa[M],fail[M],q[M],head[M],next[M],u[M],cnt1,m,n;
int a[M][26],head1[M],next1[M],u1[M],T,l[M],r[M],an[M],su[2*M];
void build()
{
int h=0,t=1;
q[1]=1;
for(;h<t;)
{
int p=q[++h];
for(int i=1;i<=26;i++)
if(a[p][i])
{
int now=fail[p];
q[++t]=a[p][i];
for(;!a[now][i];now=fail[now]);
fail[a[p][i]]=a[now][i];
}
}
return;
}
void jia(int a1,int a2)
{
cnt1++;
u[cnt1]=a2;
next[cnt1]=head[a1];
head[a1]=cnt1;
return;
}
void dfs(int a1)
{
l[a1]=++T;
for(int i=head[a1];i;i=next[i])
dfs(u[i]);
r[a1]=++T;
}
int xun(int a1)
{
int sum=0;
for(int i=a1;i;i-=i&-i)
sum+=su[i];
return sum;
}
void add(int a1,int a2)
{
for(int i=a1;i<=T;i+=i&-i)
su[i]+=a2;
}
int main()
{
scanf("%s",ch+1);
now=1;
n=strlen(ch+1);
for(int i=1;i<=n;i++)
if(ch[i]=='P')
{
pos[0]++;
pos[pos[0]]=now;
}
else if(ch[i]=='B')
now=fa[now];
else
{
if(!a[now][ch[i]-96])
{
cnt++;
a[now][ch[i]-96]=cnt;
fa[cnt]=now;
}
now=a[now][ch[i]-96];
}
for(int i=1;i<=26;i++)
a[0][i]=1;
build();
for(int i=1;i<=cnt;i++)
jia(fail[i],i);
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
u1[i]=x;
next1[i]=head1[y];
head1[y]=i;
}
dfs(1);
now=1;
pos[0]=0;
for(int i=1;i<=n;i++)
if(ch[i]=='P')
{
pos[0]++;
for(int i=head1[pos[0]];i;i=next1[i])
an[i]=xun(r[pos[u1[i]]])-xun(l[pos[u1[i]]]-1);
}
else  if(ch[i]=='B')
{
add(l[now],-1);
now=fa[now];
}
else
{
now=a[now][ch[i]-96];
add(l[now],1);
}
for(int i=1;i<=m;i++)
printf("%d\n",an[i]);
return 0;
}


AC自动机 根据dfs序建立fail树(就是将失败指针反向),每次查询x子树中有多少y的节点。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: