zoukankan      html  css  js  c++  java
  • AC自动机 数组实现

    AC自动机的实现原理是KMP + 字典树。 学AC自动机之前要先去学KMP 和 字典树。

    第一步先构建一个字典树。

     1 void Insert(){
     2     int rt = 1, len = strlen(str);
     3     for(int i = 0; i < len; i++){
     4         int id = str[i] - 'a';
     5         if(trie[rt][id] == 0){
     6             cnt[tot] = 0;
     7             fair[tot] = 0;
     8             trie[rt][id] = tot++;
     9         }
    10         rt = trie[rt][id];
    11     }
    12     cnt[rt]++;
    13 }
    插入字典树

    第二步 通过BFS来构造fair指针。

     1 void Build_tree(){
     2     queue<int> q;
     3     q.push(1);
     4     int p;
     5     while(!q.empty()){
     6         int tmp = q.front();
     7         q.pop();
     8         for(int i = 0; i < 26; i++){
     9             if(trie[tmp][i] != 0){
    10                 if(tmp == 1)
    11                     fair[trie[tmp][i]] = 1;
    12                 else{
    13                     p = fair[tmp];
    14                     while(p){
    15                         if(trie[p][i]){
    16                             fair[trie[tmp][i]] = trie[p][i];
    17                             break;
    18                         }
    19                         else p = fair[p];
    20                     }
    21                     if(!p)  fair[trie[tmp][i]] = 1;
    22                 }
    23                 q.push(trie[tmp][i]);
    24             }
    25         }
    26     }
    27 }
    构造fair指针

    第三步 进行匹配。

    统计有多少个单词的出现过。

     1 int Query(){
     2     int rt = 1, ret = 0, len = strlen(str);
     3     for(int i = 0; i < len; i++){
     4         int id = str[i] - 'a';
     5         while(!trie[rt][id] && rt != 1) rt = fair[rt];
     6         rt = trie[rt][id];
     7         if(rt == 0) rt = 1;
     8         int tmp = rt;
     9         while(tmp != 1){
    10             if(cnt[tmp] >= 0){
    11                 ret += cnt[tmp];
    12                 cnt[tmp] = -1;
    13             }
    14             else break;
    15             tmp = fair[tmp];
    16         }
    17     }
    18     return ret;
    19 }
    统计单词个数。

    AC自动机 模板题 HDU-2222 Keywords Search

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define LL long long
      4 #define ULL unsigned LL
      5 #define fi first
      6 #define se second
      7 #define lson l,m,rt<<1
      8 #define rson m+1,r,rt<<1|1
      9 #define max3(a,b,c) max(a,max(b,c))
     10 #define min3(a,b,c) min(a,min(b,c))
     11 const int INF = 0x3f3f3f3f;
     12 const LL mod = 1e9+7;
     13 typedef pair<int,int> pll;
     14 const int N = 1e5+10, M = 1e3;
     15 char str[N*10];
     16 int trie[N*10][26];
     17 int fair[N*26];
     18 int cnt[N*26];
     19 int tot = 2;
     20 void Insert(){
     21     int rt = 1, len = strlen(str);
     22     for(int i = 0; i < len; i++){
     23         int id = str[i] - 'a';
     24         if(trie[rt][id] == 0){
     25             cnt[tot] = 0;
     26             fair[tot] = 0;
     27             trie[rt][id] = tot++;
     28         }
     29         rt = trie[rt][id];
     30     }
     31     cnt[rt]++;
     32 }
     33 void Build_tree(){
     34     queue<int> q;
     35     q.push(1);
     36     int p;
     37     while(!q.empty()){
     38         int tmp = q.front();
     39         q.pop();
     40         for(int i = 0; i < 26; i++){
     41             if(trie[tmp][i] != 0){
     42                 if(tmp == 1)
     43                     fair[trie[tmp][i]] = 1;
     44                 else{
     45                     p = fair[tmp];
     46                     while(p){
     47                         if(trie[p][i]){
     48                             fair[trie[tmp][i]] = trie[p][i];
     49                             break;
     50                         }
     51                         else p = fair[p];
     52                     }
     53                     if(!p)  fair[trie[tmp][i]] = 1;
     54                 }
     55                 q.push(trie[tmp][i]);
     56             }
     57         }
     58     }
     59 }
     60 int Query(){
     61     int rt = 1, ret = 0, len = strlen(str);
     62     for(int i = 0; i < len; i++){
     63         int id = str[i] - 'a';
     64         while(!trie[rt][id] && rt != 1) rt = fair[rt];
     65         rt = trie[rt][id];
     66         if(rt == 0) rt = 1;
     67         int tmp = rt;
     68         while(tmp != 1){
     69             if(cnt[tmp] >= 0){
     70                 ret += cnt[tmp];
     71                 cnt[tmp] = -1;
     72             }
     73             else break;
     74             tmp = fair[tmp];
     75         }
     76     }
     77     return ret;
     78 }
     79 void init(){
     80     for(int i = 1; i < tot; i++){
     81         for(int j = 0; j < 26; j++)
     82             trie[i][j] = 0;
     83     }
     84     tot = 2; 
     85 }
     86 int main(){
     87     int T;
     88     scanf("%d", &T);
     89     while(T--){
     90         init();
     91         int n;
     92         scanf("%d", &n);
     93         while(n--){
     94             scanf("%s", str);
     95             Insert();
     96         }
     97         Build_tree();
     98         scanf("%s", str);
     99         printf("%d
    ", Query());
    100     }
    101     return 0;
    102 }
    HDU-2222
  • 相关阅读:
    python文件压缩示例(压缩当前目录)
    C#实现Socket聊天室
    使用微软企业库5.0进行WCF服务边界上的异常保护
    使用python的内置ctypes模块与c、c++写的dll进行交互
    Python使用tkinter库创建图形界面HelloWorld
    手动处理Team Foundation Server 2010 数据仓库和分析服务数据库
    Linux mmap
    iwconfig linux 命令行配置无线网卡
    Qt中文乱码,设置字符集
    Flex 宋体、黑体、楷体、仿宋字体样式
  • 原文地址:https://www.cnblogs.com/MingSD/p/8733762.html
Copyright © 2011-2022 走看看