• AC自动机--P3808 【模板】AC自动机(简单版)


    AC自动机是建立在KMP算法和Trie树的基础上

    一、主要步骤

    1. 将所有的模式串构建成一个Trie树
    2. 对Trie树上的所有节点求失配指针(即从根节点出发,一个串是另一个串的后缀,画图比较好理解)
    3. 利用失配指针对主串进行匹配

    代码,附注释,应该会好理解一些:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <queue>
     5 #include <cstring>
     6 using namespace std;
     7 const int maxn=2e6+10;
     8 int trie[maxn][30];
     9 int flag[maxn],fail[maxn],cnt;
    10 void insert(char *s){//构建模式串的Trie树
    11   int root=0,len=strlen(s);
    12   for (int i = 0;i < len;i++){
    13     int next=s[i]-'a';
    14     if (!trie[root][next]) trie[root][next]=++cnt;
    15     root=trie[root][next];
    16   }
    17   flag[root]++;
    18 }
    19 void getfail(){//求Fail失配数组
    20   queue<int> q;
    21   for (int i = 0;i < 26;i++){//遍历第一层的26个字母
    22     if (trie[0][i]){//如果有这个字母
    23       fail[trie[0][i]]=0;//fail指向0
    24       q.push(trie[0][i]);
    25     }
    26   }
    27   while (!q.empty()){
    28     int now=q.front();
    29     q.pop();
    30     for (int i = 0;i < 26;i++){
    31       if (trie[now][i]){//如果这一层有这个叶子节点
    32     fail[trie[now][i]]=trie[fail[now]][i];//这个叶子节点i的失配指针指向它父亲节点失配指针指向的节点的i儿子,即保证是同一个字母
    33     q.push(trie[now][i]);
    34       }
    35       else trie[now][i]=trie[fail[now]][i];//如果不存在这个i叶子节点,指向当前节点失配指针指向节点的i叶子节点,即保证是同一个字母
    36     }
    37   }
    38 }
    39 int query(char *s){//查询一共出现了多少模式串
    40   int now=0,ans=0,len=strlen(s);
    41   for (int i = 0;i < len;i++){//遍历文本串
    42     now=trie[now][s[i]-'a'];
    43     for (int j = now;j&&flag[j]!=-1;j=fail[j]){
    44       //一直向下寻找,直到匹配失败(失配指针指向根或者当前节点已经找过)
    45       ans+=flag[j];
    46       flag[j]=-1;
    47     }
    48   }
    49   return ans;
    50 }
    51 int n;
    52 char s[maxn];
    53 int main(){
    54   scanf ("%d",&n);
    55   for (int i = 0;i < n;i++) {
    56     scanf ("%s",s);
    57     insert(s);
    58   }
    59   fail[0]=0;
    60   getfail();
    61   scanf ("%s",s);
    62   printf("%d
    ",query(s));
    63   return 0;
    64 }
  • 相关阅读:
    装饰器api
    API
    Python之模块和包
    编辑后保留原URl搜索条件
    数据结构相关知识
    博客系统之评论树与评论楼相关操作
    Redis五大数据类型以及操作
    Class python31
    python_class21
    数字及字符串
  • 原文地址:https://www.cnblogs.com/very-beginning/p/13752783.html
Copyright © 2020-2023  润新知