zoukankan      html  css  js  c++  java
  • BZOJ4327 : JSOI2012 玄武密码

    对所有询问串建立AC自动机。

    然后将母串在AC自动机上跑,每走到一个点x,从x点出发沿着fail指针能到的所有前缀都是匹配成功的,暴力向上走,碰到走过的就break,这样每个点最多只会被标记一次。

    时间复杂度$O(N+100M)$。

    #include<cstdio>
    #include<cstring>
    const int N=10000003,M=100010;
    int tot,son[N][4],f[N],fail[N],q[N];bool v[N];
    int n,m,i,fin[M],len[M];char a[N],b[103];
    inline int id(char x){
      if(x=='S')return 0;
      if(x=='E')return 1;
      if(x=='W')return 2;
      return 3;
    }
    inline void insert(int p){
      int l=len[p]=strlen(b),x=0,i=0,w;
      for(;i<l;x=son[x][w],i++)if(!son[x][w=id(b[i])])f[son[x][w]=++tot]=x;
      fin[p]=x;
    }
    void make(){
      int h=1,t=0,i,x;fail[0]=-1;
      for(i=0;i<4;i++)if(son[0][i])q[++t]=son[0][i];
      while(h<=t)for(x=q[h++],i=0;i<4;i++)if(son[x][i])fail[q[++t]=son[x][i]]=son[fail[x]][i];else son[x][i]=son[fail[x]][i];
    }
    void solve(){
      for(int x=0,i=0,w;i<n;i++){
        x=son[x][w=id(a[i])];
        for(int y=x;~y;y=fail[y])if(v[y])break;else v[y]=1;
      }
    }
    inline int ask(int p){
      for(int x=fin[p],y=len[p];y;y--,x=f[x])if(v[x])return y;
      return 0;
    }
    int main(){
      scanf("%d%d%s",&n,&m,a);
      for(i=0;i<m;i++)scanf("%s",b),insert(i);
      make();
      solve();
      for(i=0;i<m;i++)printf("%d
    ",ask(i));
      return 0;
    }
    

      

  • 相关阅读:
    Windows XP中万能断点
    c#运算符 ?
    转神秘的程序员
    经典解决“线程间操作无效
    文件上传
    dowload.aspx
    mail
    js 正则
    新年快乐
    DataTable Compute
  • 原文地址:https://www.cnblogs.com/clrs97/p/4982823.html
Copyright © 2011-2022 走看看