AC自动机——解决多模匹配问题

AC自动机

  1. 什么是多模匹配问题?
    有多个模式串的匹配问题,就是多模匹配问题
  2. 处理方法
    1. 多个模式串,建立成一棵字典树
    2. 和文本串的每一位对齐匹配,模拟暴力匹配算法的过程

常规多模匹配
在这里插入图片描述
从文本串中的每一次在字典树中看是否有可以匹配的

当匹配成功文本串中的she时,也就意味着后续一定会匹配成功he she对应了字典树中的节点P,he对应了字典树中的节点Q
P和Q就是等价匹配节点,如果从P引出一条边指向Q,就可以加速匹配过程 在P下面查找节点的操作,等价于在Q下面查找节点的操作
这条等价关系边,通常在AC自动上叫做 : FAIL指针 AC自动机 = Trie + Fail指针
子节点的Fail指针需要参照父节点的Fail指针信息的,最近但的建立方式采用层序遍历

如何建立
在she中有两个节点可以建立等价边,一个是she中的h节点,一个是e节点
h节点匹配到根节点下的h
e节点匹配到根节点下h下的e,
相当于一个一一映射
建立子节点的等价关系,可以通过其父节点的等价关系

上图完全的等价匹配关系
在这里插入图片描述

建立方法:层序遍历建立:只有建立好上一层,才可以进行下一层建立

代码演示:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
using namespace std;

#define BASE 26

typedef struct Node {
   
    int flag;
    const char *str;
    struct Node *next[BASE], *fail;
} Node;
int node_cnt = 0;
Node *getNewNode() {
   
    node_cnt++;
    Node *p = (Node *)malloc(sizeof(Node));
    p->flag = 0;
    memset(p->next, 0, sizeof(p->next));
    p->fail = NULL;
    return p;
}

void insert(Node *root, const char *str) {
   
    for (int i = 0; str[i]; i++) {
   
        int ind = str[i] - 'a';
        if (root->next[ind] == NULL) root->next[ind] = getNewNode();
        root = root->next[ind];
    }
    root->flag = 1;
    root->str = strdup(str);
    return ;
}

void build_ac(Node *root) {
   
    Node **q = (Node **)malloc(sizeof(Node *) * (node_cnt + 5));//建立一个队列
    int head = 0, tail = 0;//首尾指针
    root->fail = NULL;//根节点没有fail指针
    for (int i = 0; i < BASE; i++) {
   
        if (root->next[i] == NULL) continue;
        root->next[i]->fail = root;
        q[tail++] = root->next[i];
    }
    while (head < tail) {
   
        Node *p = q[head++];//取出队首元素
        for (int i = 0; i < BASE; i++) {
   //遍历该元素的所有子孩子
            Node *c = p->next[i], *k = p->fail;//c为该节点的子孩子,子节点的fail 指针需要依靠根节点进行
            if (c == NULL) continue;//没有该节点
            while (k && k->next[i] == NULL) k = k->fail;//当根节点有fail指针,但是k节点没有第i个子孩子,,接着向上找
            if (k == NULL) k = root;//如果k最终结果是空,那么a该节点的fail指针指向根节点
            if (k->next[i]) k = k->next[i];//如果找到了,k的next[i]就是该节点的fail
            c->fail = k;
            q[tail++] = c;//放入该节点
        }
    }
    free(q);
    return ;
}

void match(Node *root, const char *text) {
   
    Node *p 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值