bzoj 2434 [Noi2011]阿狸的打字机——AC自动机

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2434

dfs AC自动机,走过的点权值+1,回溯的时候权值-1;走到询问的 y 串的节点,看一下此时 x 串 fail 树子树和即可。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int rdn()
{
  int ret=0;bool fx=1;char ch=getchar();
  while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
  while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
  return fx?ret:-ret;
}
const int N=1e5+5,K=26;
int n,m,tot=1,dy[N],c[N][K],tc[N][K],fa[N],fl[N];
int hd[N],xnt,to[N<<1],nxt[N<<1],dfn[N],ot[N],tim;
int h2[N],t2[N],nt2[N],ans[N];
int q[N],f[N]; char s[N];
void add(int x,int y)
{to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;fl[y]=x;}
void get_fl()
{
  int he=0,tl=0;
  for(int i=0,v;i<26;i++)
    if((v=c[1][i]))q[++tl]=v,add(1,v),tc[1][i]=v;
    else tc[1][i]=1;
  while(he<tl)
    {
      int k=q[++he],pr=fl[k];
      for(int i=0,v;i<26;i++)
    if((v=c[k][i]))
      q[++tl]=v,add(tc[pr][i],v),tc[k][i]=v;
    else tc[k][i]=tc[pr][i];
    }
}
void ini_dfs(int cr)
{
  dfn[cr]=++tim;
  for(int i=hd[cr];i;i=nxt[i])
    ini_dfs(to[i]);
  ot[cr]=tim;
}
void Inc(int x,int k){for(;x<=tot;x+=(x&-x))f[x]+=k;}
int qry(int x){int ret=0;for(;x;x-=(x&-x))ret+=f[x];return ret;}
void dfs(int cr)
{
  Inc(dfn[cr],1);
  for(int i=h2[cr];i;i=nt2[i])
    ans[i]=qry(ot[t2[i]])-qry(dfn[t2[i]]-1);
  for(int i=0;i<26;i++)
    if(c[cr][i])dfs(c[cr][i]);
  Inc(dfn[cr],-1);
}
int main()
{
  scanf("%s",s+1); n=strlen(s+1);
  int cr=1,cnt=0;
  for(int i=1;i<=n;i++)
    {
      if(s[i]>='a')
    {
      c[cr][s[i]-'a']=++tot;
      fa[tot]=cr; cr=tot;
    }
      else if(s[i]=='B')cr=fa[cr];
      else dy[++cnt]=cr;
    }
  get_fl(); ini_dfs(1);
  m=rdn();
  for(int i=1;i<=m;i++)
    {
      int u=rdn(),v=rdn();
      u=dy[u]; v=dy[v];
      t2[i]=u;nt2[i]=h2[v];h2[v]=i;
    }
  dfs(1);
  for(int i=1;i<=m;i++)printf("%d\n",ans[i]);
  return 0;
}

 

posted on 2019-04-30 21:13  Narh  阅读(198)  评论(0编辑  收藏  举报

导航