【暑假】[实用数据结构] AC自动机

来源:互联网 发布:淘宝客域名注册 编辑:程序博客网 时间:2024/05/29 09:32
Aho-Corasick自动机

 算法:

 <功能>

  AC自动机用于解决文本一个而模板有多个的问题。

  AC自动机可以成功将多模板匹配,匹配意味着算法可以找到每一个模板在文本中出现的位置。

 <解释>

  KMP中对模板构造失配边,多模板每条模板独立构造失配边太过麻烦。

  算法利用Trie+KMP中的失配边。insert(模板) 构造Trie+ getFail添加失配边->AC自动机的状态转移图。

  匹配文本串text时只需要调用find,find依次匹配text中的每一个字符失败则沿着失配边走,在匹配路径上如果遇到单词结点(val != 0 )即相当于匹配成功。

  但需要注意到:可能有作为当前后缀的单词已经成功匹配,所以需要加入后缀链接last[] 在每一个结点都要处理这种情况。last递推得到。

 

作者所给模板如下

 

 1 struct AhoCorasickAutomata { 2   int ch[MAXNODE][SIGMA_SIZE]; 3   int f[MAXNODE];    // fail函数 4   int val[MAXNODE];  // 每个字符串的结尾结点都有一个非0的val 5   int last[MAXNODE]; // 输出链表的下一个结点 6   int cnt[MAXS]; 7   int sz; 8  9   void init() {10     sz = 1;11     memset(ch[0], 0, sizeof(ch[0]));12     memset(cnt, 0, sizeof(cnt));13     ms.clear();14   }15 16   // 字符c的编号17   int idx(char c) {18     return c-'a';19   }20 21   // 插入字符串 v必须非022   void insert(char *s, int v) {23     int u = 0, n = strlen(s);24     for(int i = 0; i < n; i++) {25       int c = idx(s[i]);26       if(!ch[u][c]) {27         memset(ch[sz], 0, sizeof(ch[sz]));28         val[sz] = 0;29         ch[u][c] = sz++;30       }31       u = ch[u][c];32     }33     val[u] = v;34     ms[string(s)] = v;35   }36 37   // 递归打印以结点j结尾的所有字符串38   void print(int j) {39     if(j) {40       cnt[val[j]]++;41       print(last[j]);42     }43   }44 45   // 在T中找模板46   int find(char* T) {47     int n = strlen(T);48     int j = 0; // 当前结点编号 初始为根结点49     for(int i = 0; i < n; i++) { // 文本串当前指针50       int c = idx(T[i]);51       while(j && !ch[j][c]) j = f[j]; // 顺着细边走 直到可以匹配52       j = ch[j][c];53       if(val[j]) print(j);54       else if(last[j]) print(last[j]); // 找到了 55     }56   }57 58   // 计算fail函数59   void getFail() {60     queue<int> q;61     f[0] = 0;62     // 初始化队列63     for(int c = 0; c < SIGMA_SIZE; c++) {64       int u = ch[0][c];65       if(u) { f[u] = 0; q.push(u); last[u] = 0; }66     }67     // 按BFS顺序计算fail68     while(!q.empty()) {69       int r = q.front(); q.pop();70       for(int c = 0; c < SIGMA_SIZE; c++) {71         int u = ch[r][c];72         if(!u) continue;73         q.push(u);74         int v = f[r];75         while(v && !ch[v][c]) v = f[v];76         f[u] = ch[v][c];77         last[u] = val[f[u]] ? f[u] : last[f[u]];78       }79     }80   }81 82 };

 

0 0
原创粉丝点击