zoukankan      html  css  js  c++  java
  • 洛谷P2414 [NOI2011]阿狸的打字机(AC自动机)

    传送门

    考虑一下,如果串B在串A中出现过,那么A的fail指针必定直接或间接指向B

    那么我们可以把fail树建起来,那么就变成B代表的节点的子树里有多少节点属于A

    然后这就是一个序列统计问题,直接用dfs序+树状数组可以维护

    具体的操作就是,先把每一个点有关的询问给存起来,然后等到在trie树上一遍dfs,当dfs到这个串的结束节点说明所有有关这个串的节点都被遍历到(可以在遍历的时候顺便用树状数组维护序列和),然后对每一个询问查一下子树和即可

      1 //minamoto
      2 #include<iostream>
      3 #include<cstdio>
      4 #include<cstring>
      5 #include<queue>
      6 #include<algorithm>
      7 using namespace std;
      8 const int N=100005;
      9 int tot=1;
     10 struct node{
     11     int num,type;
     12     node(){}
     13     node(int num,int type):num(num),type(type){}
     14 };
     15 queue<node> q;
     16 int ch[N][26],End[N],word,fa[N],fail[N],dis[N];
     17 inline int insert(int p,int c){
     18     if(ch[p][c]) return ch[p][c];
     19     ch[p][c]=++tot,fa[tot]=p;return tot;
     20 }
     21 inline int back(int p){return fa[p];}
     22 inline void ed(int p){End[p]=++word,dis[word]=p;}
     23 void build(){
     24     for(int i=0;i<26;++i)
     25     if(ch[1][i])
     26     q.push(node(ch[1][i],i)),fail[ch[1][i]]=1;
     27     while(!q.empty()){
     28         node now=q.front();q.pop();
     29         if(fail[now.num]!=1){
     30             int trail=fail[fa[now.num]];
     31             while(true){
     32                 if(ch[trail][now.type]){trail=ch[trail][now.type];break;}
     33                 if(trail==1) break;trail=fail[trail];
     34             }
     35             fail[now.num]=trail;
     36         }
     37         for(int i=0;i<26;++i)
     38         if(ch[now.num][i])
     39         q.push(node(ch[now.num][i],i));
     40     }
     41 }
     42 int ver[N<<1],Next[N<<1],head[N],E=0;
     43 inline void add(int u,int v){
     44     ver[++E]=v,Next[E]=head[u],head[u]=E;
     45 }
     46 int ver1[N],Next1[N],head1[N],edge1[N],E1=0;
     47 inline void add1(int u,int v,int num){
     48     ver1[++E1]=v,Next1[E1]=head1[u],head1[u]=E1,edge1[E1]=num;
     49 }
     50 int c[N<<1];
     51 inline void addd(int x,int y){
     52     for(;x<=tot;x+=x&-x) c[x]+=y;
     53 }
     54 inline int sum(int x){
     55     int res=0;
     56     for(;x;x-=x&-x) res+=c[x];
     57     return res;
     58 }
     59 int dfn[N],sz[N],cnt=0,ans[N];
     60 bool book[N];
     61 void dfsfail(int u){
     62     dfn[u]=++cnt,sz[u]=1,book[u]=true;
     63     for(int i=head[u];i;i=Next[i]){
     64         int v=ver[i];
     65         if(!book[v]) dfsfail(v),sz[u]+=sz[v];
     66     }
     67 }
     68 void dfstrie(int u){
     69     addd(dfn[u],1);
     70     if(End[u]){
     71         for(int i=head1[End[u]];i;i=Next1[i]){
     72             int v=ver1[i],x=dis[v];
     73 //            printf("%d %d %d
    ",v,x,edge1[i]);
     74             ans[edge1[i]]=sum(dfn[x]+sz[x]-1)-sum(dfn[x]-1);
     75         }
     76     }
     77     for(int i=0;i<26;++i)
     78     if(ch[u][i]) dfstrie(ch[u][i]);
     79     addd(dfn[u],-1);
     80 }
     81 char s[N];int len,m,st;
     82 int main(){
     83 //    freopen("testdata.in","r",stdin);
     84     scanf("%s",s+1);
     85     len=strlen(s+1);
     86     for(st=1;st<=len;++st)
     87     if(s[st]!='B'&&s[st]!='P') break;
     88     int p=insert(1,s[st]-'a');
     89     for(int i=st+1;i<=len;++i){
     90         if(s[i]=='B') p=back(p);
     91         else if(s[i]=='P') ed(p);
     92         else p=insert(p,s[i]-'a');
     93     }
     94     scanf("%d",&m);
     95     for(int i=1,u,v;i<=m;++i){
     96         scanf("%d%d",&u,&v);
     97         add1(v,u,i);
     98     }
     99     build();
    100     for(int i=2;i<=tot;++i)
    101     add(fail[i],i),add(i,fail[i]);
    102     dfsfail(1),dfstrie(1);
    103     for(int i=1;i<=m;++i) printf("%d
    ",ans[i]);
    104     return 0;
    105 }
  • 相关阅读:
    「BZOJ1954」Pku3764 The xor – longest Path
    【bzoj4260】【Codechef REBXOR】
    BZOJ_3012_[Usaco2012 Dec]First!
    【bzoj1174】[Balkan2007]Toponyms
    String
    前缀和
    [POI2008] CLO
    [Scoi2010] 游戏
    CodeForces892E
    并查集的删除操作
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9643024.html
Copyright © 2011-2022 走看看