• 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
    ",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
    ",ans[i]);
      }
    View Code
  • 相关阅读:
    有序数组(类模板)
    BUUCTF-Web Comment
    BUUCTF-web NiZhuanSiWei
    2020数字中国创新大赛虎符网络安全赛道-pwn count
    BUUCTF-Web Easy Calc
    xctf-web fakebook
    xctf-web supersqli
    xctf-pwn pwn200
    xctf-pwn level3
    利用updatexml()报错注入mysql
  • 原文地址:https://www.cnblogs.com/maijing/p/4698989.html
Copyright © 2020-2023  润新知