zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    [转载]微信企业号开发如何建立连接
    【VB技巧】VB静态调用与动态调用dll详解
    DevExpress 中 汉化包 汉化方法
    DevExpress汉化(WinForm)
    DevExpress 中 WaitForm 使用
    DevExpress 中 DateEdit 控件 格式化显示和编辑的日期格式为: yyyy-MM-dd
    DevExpress 中 用 LookUpEdit 控件 代替 ComboBoxEdit 控件来绑定 DataTable
    asp.net 大文上传配置
    DevExpress中的lookupedit的使用方法详解
    DevExpress控件使用小结
  • 原文地址:https://www.cnblogs.com/very-beginning/p/13752783.html
Copyright © 2011-2022 走看看