• 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
  • 相关阅读:
    ....
    CodeForces 375A(同余)
    POJ 2377 Bad Cowtractors (最小生成树)
    POJ 1258 AgriNet (最小生成树)
    HDU 1016 Prime Ring Problem(全排列)
    HDU 4460 Friend Chains(bfs)
    POJ 2236 Wireless Network(并查集)
    POJ 2100 Graveyard Design(尺取)
    POJ 2110 Mountain Walking(二分/bfs)
    CodeForces 1059B Forgery(模拟)
  • 原文地址:https://www.cnblogs.com/MingSD/p/8733762.html
Copyright © 2020-2023  润新知