zoukankan      html  css  js  c++  java
  • 【BZOJ 3172】[Tjoi2013]单词 AC自动机

    关于AC自动机:一个在kmp与Trie的基础上建立的数据结构,关键在于Trie树结构与fail指针,他们各有各的应用。在AC自动机里最典型的就是多串匹配,原本效率为O(n*l+n*l+m*l),(n是模式串个数,m是匹配串长度,l是模式串平均长度),那么他的效率甚至有时不如多个kmp,虽然很好被卡但平均效率还是不错的。如果在此基础上加上last指针,作用为减少匹配过程中不必要的跳fail,那么就会好一些,但是效率不会有显著的提升而且仍然很好卡,目前为O(n*l+n*l+m*n)。在此基础上我们就可以加上Trie图,Trie图作用就是加快建fail以及在匹配过程中的转移,这时效率就会有不错的提升,建fail的时间复杂度也就更有保证,但是仍然会被卡,目前为O(n*l+n*l+m*n)。到此为止我们的时间复杂度已经是比较优秀的了,但是我们还可以让他更加优秀,我们可以在加上fail树,关于fail树,那么我们在匹配过程中就可以省去跳跃的过程,现在我们的时间复杂度已经到了O(n*l+n*l+m+n*l),已经有了巨大的飞跃,而且基本不会被卡。

    我的程序是倒数第二层优化的,慢死。

    #include <vector>
    #include <cstring>
    #include <cstdio>
    #include <iostream>
    const int N=1000000;
    char s[201][N];
    struct Trie{
      Trie *ch[26],*fail,*last;
      std::vector<int> mem;
    }node[N+1],*root,*q[N+1];
    int n,sz,sum[201];
    inline Trie *newnode(){
      return &node[++sz];
    }
    inline void insert(char *w,int id){
      Trie *p=root;
      for(int i=0;w[i];i++){
        if(p->ch[w[i]-'a']==NULL)p->ch[w[i]-'a']=newnode();
        p=p->ch[w[i]-'a'];
      }
      p->mem.push_back(id);
    }
    inline void build(){
      q[0]=root;
      for(int i=0,j=0;i<=j;i++)
        for(int l=0;l<26;l++)
          if(q[i]->ch[l]){
            q[++j]=q[i]->ch[l];
            q[j]->fail=q[i]==root?root:q[i]->fail->ch[l];
            q[j]->last=q[j]->fail->mem.size()?q[j]->fail:q[j]->fail->last;
          }
          else
            q[i]->ch[l]=q[i]==root?root:q[i]->fail->ch[l];
    }
    inline void read(){
      scanf("%d",&n),root=node;
      for(int i=1;i<=n;i++)
        scanf("%s",s[i]),insert(s[i],i);
      build();
    }
    inline void work(){
      for(int k=1;k<=n;k++){
        Trie *now=root;
        for(int i=0;s[k][i];i++){
          now=now->ch[s[k][i]-'a'];
          for(int j=0;j<now->mem.size();j++)
            sum[now->mem[j]]++;
          for(Trie *p=now->last;p;p=p->last)
            for(int j=0;j<p->mem.size();j++)
              sum[p->mem[j]]++;
        }
      }
    }
    inline void print(){
      for(int i=1;i<=n;i++)
        printf("%d
    ",sum[i]);
    }
    int main(){
      read();
      work();
      print();
    }
  • 相关阅读:
    团队作业2-《需求规格说明书》
    团队作业 —— 团队选题
    自我介绍+软工五问
    团队作业5——测试与发布(Alpha版本)
    结对项目(与陈超国)
    个人项目wordcount
    自我介绍+软工5问
    个人项目(C语言)
    自我介绍+软工五问
    第三篇 Scrum冲刺博客
  • 原文地址:https://www.cnblogs.com/TSHugh/p/7517755.html
Copyright © 2011-2022 走看看