NOI2011 阿狸的打字机

http://www.lydsy.com/JudgeOnline/problem.php?id=2434

AC自动机。

首先第1行的输入就是让我们建AC自动机。。。。。。(提示好大)

记第i个字符串在AC自动机里面的点编号为pos[i]。

其实询问就是:对于在AC自动机里pos[y]到根的路径上的所有结点,有多少个在fail-tree中在以pos[x]为根的子树中。

我们可以先在fail-tree中DFS,求出每个点i的DFS序idx[i],子树中最小的DFS序l[i]和子树中最大DFS序r[i],并建立树状数组。

然后在AC自动机里DFS,访问点i就在idx[i]位置+1,离开点i就在idx[i]位置-1,这样就是维护了点i到根的路径上的所有结点。

然后在树状数组里询问即可。

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<fstream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<utility>
#include<set>
#include<bitset>
#include<vector>
#include<functional>
#include<deque>
#include<cctype>
#include<climits>
#include<complex>
//#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj
 
using namespace std;

typedef long long LL;
typedef double DB;
typedef pair<int,int> PII;
typedef complex<DB> CP;

#define mmst(a,v) memset(a,v,sizeof(a))
#define mmcy(a,b) memcpy(a,b,sizeof(a))
#define re(i,a,b)  for(i=a;i<=b;i++)
#define red(i,a,b) for(i=a;i>=b;i--)
#define fi first
#define se second
#define m_p(a,b) make_pair(a,b)
#define SF scanf
#define PF printf
#define two(k) (1<<(k))

template<class T>inline T sqr(T x){return x*x;}
template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;}
template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;}

const DB EPS=1e-9;
inline int sgn(DB x){if(abs(x)<EPS)return 0;return(x>0)?1:-1;}
const DB Pi=acos(-1.0);

inline int gint()
  {
        int res=0;bool neg=0;char z;
        for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
        if(z==EOF)return 0;
        if(z=='-'){neg=1;z=getchar();}
        for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());
        return (neg)?-res:res; 
    }
inline LL gll()
  {
      LL res=0;bool neg=0;char z;
        for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
        if(z==EOF)return 0;
        if(z=='-'){neg=1;z=getchar();}
        for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());
        return (neg)?-res:res; 
    }

const int maxN=100000;
const int maxM=100000;
const int maxlen=100000;

int N,M;
char s[maxlen+100];
int pos[maxN+100];

int now,first[maxlen+100];
struct Tedge{int v,next;}edge[maxlen+100];

inline void addedge(int u,int v)
  {
      now++;
      edge[now].v=v;
      edge[now].next=first[u];
      first[u]=now;
  }

int cnt,fa[maxlen+100],fail[maxlen+100],ch[maxlen+100][30];
int head,tail,que[maxlen+100];
inline void build()
  {
      int i,p;
      cnt=p=1;
      fa[1]=0;
      int len=strlen(s+1);
      re(i,1,len)
        if(s[i]=='B')
                p=fa[p];
        else if(s[i]=='P')
            pos[++N]=p;
          else
                {
              if(!ch[p][s[i]-'a'])ch[p][s[i]-'a']=++cnt,fa[cnt]=p;
              p=ch[p][s[i]-'a'];  
            }
      mmst(first,-1);now=-1;
      fail[que[head=tail=1]=1]=1;
      while(head<=tail)
        {
            int u=que[head++];
            re(i,0,25)if(ch[u][i])
              {
                  int v=ch[u][i];
                  if(u==1)
                    fail[que[++tail]=v]=1;
                  else
                    {
                        int temp=fail[u];
                                while(temp!=1 && !ch[temp][i])temp=fail[temp];
                                if(ch[temp][i])temp=ch[temp][i];
                                fail[que[++tail]=v]=temp;
                            }
                addedge(fail[v],v);
              }
        }
  }

int ge,idx[maxlen+100],l[maxlen+100],r[maxlen+100];

int top,sta[maxlen+100],last[maxlen+100];
inline void DFS1()
  {
      idx[sta[top=1]=1]=ge=1;
      last[top]=first[1];
      while(top>=1) 
        {
            int u=sta[top],i=last[top],v;
            for(v=edge[i].v;i!=-1;i=edge[i].next,v=edge[i].v)
              {
                  idx[sta[++top]=v]=++ge;
                  last[top]=first[v];
                  last[top-1]=edge[i].next;
                  break;
              }
            if(i==-1)
              {
                  l[u]=r[u]=idx[u];
                  for(i=first[u],v=edge[i].v;i!=-1;i=edge[i].next,v=edge[i].v)upmin(l[u],l[v]),upmax(r[u],r[v]);
                  top--;
              }
        }
  }

#define lowbit(a) ((a)&(-(a)))
int tree[maxlen+100];
inline void update(int a,int v){for(;a<=cnt;a+=lowbit(a))tree[a]+=v;}
inline int ask(int l,int r)
  {
      int res=0;
      for(;r>=1;r-=lowbit(r))res+=tree[r];
      for(l--;l>=1;l-=lowbit(l))res-=tree[l];
      return res;
  }

vector<PII> Q[maxlen+100];
int ans[maxM+100];

inline void DFS2()
  {
      sta[top=1]=1;
      last[top]=0;
      while(top>=1)
        {
            int u=sta[top],i=last[top],v,j;
            for(v=ch[u][i];i<26;i++,v=ch[u][i])if(v)
              {
                  sta[++top]=v;
                  last[top]=0;
                  last[top-1]=i+1;
                  update(idx[v],1);
                  re(j,0,int(Q[v].size())-1)
                    {
                        int x=Q[v][j].fi,w=Q[v][j].se;
                        ans[w]=ask(l[x],r[x]);
                    }
                  break;
              }
            if(i==26)update(idx[u],-1),top--;
        }
  }

int main()
  {
      freopen("type.in","r",stdin);
      freopen("type.out","w",stdout);
      int i;
      scanf("%s\n",s+1);
      build();
      M=gint();
      re(i,1,M)
        {
              int x=gint(),y=gint();
                Q[pos[y]].push_back(PII(pos[x],i));    
          }
        DFS1();
        DFS2();
        re(i,1,M)PF("%d\n",ans[i]);
  }
View Code

 

posted @ 2015-08-03 12:00  maijing  阅读(224)  评论(0编辑  收藏  举报