AC自动机 (uva 1449)

什么是ac自动机?(最开始的幻想是能够自动ac程序题的程序>_<,美梦啊!) 

ac自动机全称叫做Aho-Corasick自动机(不是accept)。我们都知道在模式匹配,如果只有一个模板我们使用的是KMP算法,但是如果存在很多的模板呢?我们应该如何做呢?难道将每次查询一个模板都要遍历一遍整个字符串?这样时间复杂度肯定会不够的,所有我们就要使用一种新的算法,它就是ac自动机。

ac自动机其实就是将trie(前缀树)与KMP算法结合起来,将所有模板建立一颗前缀树,然后在计算出一个Fail函数。

Fail函数的作用就是建立其下图中虚线的边。


我的模板:

struct Aho-Corasick{
  int ch[maxnode][sigma_size];
  int val[maxnode];
  int f[maxnode];
  int last[maxnode];
  int sz;
  void clears() {sz=1;memset(ch[0],0,sizeof(ch[0]));}
  int idx(char c){return c-'a';}
  int  insert(char *s,int v){
    int u=0,n=strlen(s);
    for(int i=0;i<n;i++){
      int c=idx(s[i]);
      if (!ch[u][c]) {     
        memset(ch[sz],0,sizeof(ch[sz]));
        val[sz]=0;         
        ch[u][c]=sz++;    
      }
      u=ch[u][c];          
    }
    val[u]=v;
    return 0;
  }


int getFail(){
  queue <int> q;
  f[0]=0;

//初始化队列
  for (int c=0;c<sigma_size;c++){
    int u=ch[0][c];
    if (u){f[u]=0;q.push(u);last[u]=0;}
  }

//BFS 顺序计算失配函数
  while (!q.empty()){
     int r=q.front();q.pop();
      for (int c=0;c<sigma_size;c++){
        int u=ch[r][c];
        if (!u) continue;
        q.push(u);
        int v=f[r];
        while (v&&!ch[v][c]) v=f[v];
        f[u]=ch[v][c];
        last[u]=val[f[u]]?f[u]:last[f[u]];
      }
    }
}


void find (char *T){
  int n=strlen(T);
  int j=0;
  for (int i=0;i<n;i++){
    int c=idx(T[i]);
    while (j&&!ch[j][c]) j=f[j];
    j=ch[j][c];
    if (val[j]) print(j);
    else if (last[j]) print(last[j]);
   }
}


void print(int j){
  if (j){
    printf("%d: %d\n",j,val[j]);
    print(last[j]);
  }
}


}

如果读者对trie与KMP算法都很熟悉的话,应该可以看得懂上面的代码,但是与也会存在一些问题比如last[]数组是什么?

和trie一样,我们认为所有val[j]>0的节点都是单词节点,但是与trie不同的是,同一个节点可能对应多个字符串结尾如上图中的5号节点,它分别对应了{he,she}

这个last[j]代表的是沿着虚线走,遇到的下一个单词节点编号,我们用它来降低时间复杂度。它还有个高大上的名字叫做后缀链接。


uva  1449 是一道裸地ac自动机题,可以用它作为练习.

我的代码:

#include <cstdio>
#include <cstring>
#include <queue>
#include <map>
#include <string>
const int sigma_size =26;
const int maxnode = 11000;
using namespace std;
struct AC{
  int ch[maxnode][sigma_size];
  int val[maxnode];
  int f[maxnode];
  int last[maxnode];
  int cnt[maxnode];
  int sz;
  void clears() {sz=1;memset(ch[0],0,sizeof(ch[0]));memset(cnt,0,sizeof(cnt));}
  int idx(char c){return c-'a';}
  int  insert(char *s,int v){
    int u=0,n=strlen(s);
    for(int i=0;i<n;i++){
      int c=idx(s[i]);
      if (!ch[u][c]) {
        memset(ch[sz],0,sizeof(ch[sz]));
        val[sz]=0;
        ch[u][c]=sz++;
      }
      u=ch[u][c];
    }
    val[u]=v;
    return 0;
  }


int getFail(){
  queue <int> q;
  f[0]=0;
  for (int c=0;c<sigma_size;c++){
    int u=ch[0][c];
    if (u){f[u]=0;q.push(u);last[u]=0;}
  }
  while (!q.empty()){
     int r=q.front();q.pop();
      for (int c=0;c<sigma_size;c++){
        int u=ch[r][c];
        if (!u) continue;
        q.push(u);
        int v=f[r];
        while (v&&!ch[v][c]) v=f[v];
        f[u]=ch[v][c];
        last[u]=val[f[u]]?f[u]:last[f[u]];
      }
    }
}


void find (char *T){
  int n=strlen(T);
  int j=0;
  for (int i=0;i<n;i++){
    int c=idx(T[i]);
    while (j&&!ch[j][c]) j=f[j];
    j=ch[j][c];
    if (val[j]) print(j);
    else if (last[j]) print(last[j]);
   }
}


void print(int j){
  if (j){
    cnt[val[j]]++;
    print(last[j]);
  }
}


};
AC ac;
map <string,int> qqq;
char text[1000010],P[155][80];
int n;
int main (){
  while (scanf("%d",&n)==1&&n){
    ac.clears();
    for (int i=1;i<=n;i++){
      scanf("%s",P[i]);
      ac.insert(P[i],i);
    }
    ac.getFail();
    scanf("%s",text);
    ac.find(text);
    int best=-1;
    qqq.clear();
    for (int i=1;i<=n;i++){
      if (ac.cnt[i]>best) best=ac.cnt[i];
      //printf("%d %d\n",i,ac.cnt[i]);
    }
    for (int i=1;i<=n;i++){
      if (ac.cnt[i]==best) qqq[string(P[i])]=1;
    }
    printf("%d\n",best);
    for (int i=1;i<=n;i++)
      if (qqq[string(P[i])]) printf("%s\n",P[i]);
  }
  return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python AC自动机是一个用于字符串匹配的算法,它可以高效地在一段文本中查找多个预定义的模式。它的实现可以使用多种库,其中包括ac自动机python和ahocorasick-python。 ac自动机python是一个对标准的ac自动机算法进行了完善和优化的实现,适用于主流的Python发行版,包括Python2和Python3。它提供了更准确的结果,并且可以通过pip进行安装,具体的安装方法可以参考官方文档或者使用pip install命令进行安装。 ahocorasick-python是另一个实现AC自动机的库,它也可以用于Python2和Python3。你可以通过官方网站或者GitHub源码获取更多关于该库的信息和安装指南。 对于AC自动机的使用,一个常见的例子是在一段包含m个字符的文章中查找n个单词出现的次数。要了解AC自动机,需要有关于模式树(字典树)Trie和KMP模式匹配算法的基础知识。AC自动机的算法包括三个步骤:构造一棵Trie树,构造失败指针和模式匹配过程。在构造好AC自动机后,可以使用它来快速地在文本中查找预定义的模式,并统计它们的出现次数。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [ahocorasick-python:AC自动机python的实现,并进行了优化。 主要修复了 查询不准确的问题](https://download.csdn.net/download/weixin_42122986/18825869)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Python实现多模匹配——AC自动机](https://blog.csdn.net/zichen_ziqi/article/details/104246446)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值