AC-BM算法原理与代码实现(模式匹配)

本文详细介绍了AC-BM算法的工作原理,该算法结合了Aho-Corasick算法和Bad Character Shift、Good Prefix Shift技术,用于高效地进行模式匹配。文章还提供了C语言的实现代码,包括AC树的构建、搜索算法和相关辅助函数,展示了如何创建、调整和搜索模式树。
摘要由CSDN通过智能技术生成
AC-BM算法将待匹配的字符串集合转换为一个类似于Aho-Corasick算法的树状有限状态自动机,但构建时不是基于字符串的后缀而是前缀。匹配时,采取自后向前的方法,并借用BM算法的坏字符跳转(Bad Character Shift)和好前缀跳转(Good Prefix Shift)技术。
   坏字符跳转即当字符串树中的字符与被匹配内容x失配时,将字符串树跳转到下一个x的出现位置,如果x的字符串树不存在,则将字符串树向左移动字符串树的最小字符串长度。好前缀跳转即当字符串树中的字符与被匹配内容x失配时,将字符串树跳转到字符串树中一个与被测正文部分等同的位置。这个等同部分可以是字符串树中某字符串的子串(子串跳转),也可以是一个字符串的后缀(后缀跳转)。

   当既有好后缀跳转,又有坏字符跳转时,则判断如果有后缀跳转,就使用好前缀跳转(子串跳转与后缀跳转的最小值);否则,使用好前缀跳转与坏字符跳转的最大值。
具体C实现代码如下:
AC-BM.h文件:
#ifndef _AC_BM_H
#define _AC_BM_H
#define PATTERN_LEN 1024
#define MAX_ITEMS 20
/// 模式树节点结构
typedef struct _pattern_tree_node
{
 int label ;         // 标识, -2 根节点, -1 中间节点, n 第n个字串尾节点
 int depth ;           // 节点深度
 
 unsigned char ch ;       // 节点对应的字符
 int GSshift ;        // 好字串位移
 int BCshift ;
 unsigned char one_child ;     // 其中的一个子索引字符
 struct _pattern_tree_node *childs[256] ; // 256个字符的对应节点指针
 int nchild ;                             // 子节点个数
 struct _pattern_tree_node *parent ;      // 父节点
} pattern_tree_node ;

// 关键字数据结构
typedef struct _pattern_data
{
 unsigned char data[PATTERN_LEN] ; // 关键字字串
 int len ;                         // 关键字字串长
} pattern_data ;

// 模式树结构
typedef struct _pattern_tree
{
 pattern_tree_node *root ;  // 树根节点
 int max_depth ;     // 最大字串深度
 int min_pattern_size ;          // 最短的字串长度
 int BCshift[256] ;             // 256个字符中坏字符的shift
 pattern_data *pattern_list ;  // 指向节点数组第一个字串的指针
 int pattern_count ;             // 包含的字串个数
} pattern_tree ;

// 匹配信息结构体
typedef struct _matched_info
{
 int pattern_i ;               // 关键字在关键字数组中的index
 unsigned long offset ;        // 在待匹配文本text中的偏移值
} matched_info_t ;
// 创建 模式树
int ACtree_build (pattern_tree *ptree,
      pattern_data *patterns,
      int npattern) ;
// 打印 当前节点及其所有后缀节点
void _print_tree (pattern_tree_node *root) ;
// 打印 整个模式树
void ACtree_print_tree (pattern_tree *ptree);
// 打印 搜索结果
int match_resualt_printf_ex (unsigned char *text,
        pattern_data *patterns,
        int npattern,
        matched_info_t matched_items[],
        int nmatched);
// 释放 模式树空间
void _clean_tree(pattern_tree_node *root) ;
// 设置 模式树的BCshift
int ACtree_compute_BCshifts (pattern_tree *ptree) ;
// 创建 ac_bm模式树
pattern_tree *acbm_init (pattern_data *patterns, int npattern) ;
// 释放 ac_bm模式树空间
void acbm_clean (pattern_tree *ptree) ;
// ac_bm搜索算法改进版
int acbm_search (pattern_tree *ptree, 
     unsigned char *text,
     int text_len,
     matched_info_t matched_items[], 
     int nmax_index);
// 计算并调整ACTree模式树的BCshift和GSshift
int ACtree_compute_shifts(pattern_tree *ptree) ;
// 计算并调整ACTree模式树的GSshift
int ACtree_compute_GSshifts(pattern_tree *ptree) ;
// 初始化ACTree的GSshift
int ACtree_init_GSshifts(pattern_tree *ptree) ;
// 初始化当前节点的GSshift
int _init_GSshifts(pattern_tree_node *root, int shift) ;
// 调整ACTree中关键字pat1的GSshift
int set_GSshift (pattern_tree *ptree,
     unsigned char *pat, 
     int depth,
     int shift) ;
// 调整ACTree中关键字pat1因pat2而发生变化的GSshift
int compute_GSshift(pattern_tree *ptree,
        unsigned char *pat1,
     int pat1_len,
     unsigned char *pat2,
     int pat2_len) ;
#endif
AC-BM.c文件如下:
// 头文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "ac_bm.h"
// 宏定义
//#define CASE_SENSITIVE
//#define DEBUG_SEARCH

unsigned char mychar[100];

/*--------------------------------------------------------------------------
* 函数名:
*    ACTree_bulid

* 函数功能:
*    创建ACtree模式树,包括各个节点,字符索引,及其他的信息,ptree指向根节点

* 参数说明:
*    pattern_tree *ptree    : 指向ACTree的指针
*    pattern_data *patterns : 关键字字串数组
*    int npattern           : 关键字字串个数

* 返回值类型:   int
*    0 : 创建成功
*   -1 : 出错
----------------------------------------------------------------------------*/
int ACtree_build (pattern_tree *ptree,
      pattern_data *patterns,
      int npattern)
{
 int i ;
 pattern_tree_node *root = NULL, *parent = NULL ;
 unsigned char ch ;
 int max_pattern_len = 0, min_pattern_len = PATTERN_LEN ;
 if (NULL == ptree || NULL == patterns || npattern < 0)
 {
  goto err ;
 }
 
 root = (pattern_tree_node *) malloc (sizeof (pattern_tree_node)) ;
 if (NULL == root)
 {
  goto err ;
 }
 memset (root, 0, sizeof (pattern_tree_node)) ;
 root->label = -2 ;    // 树根标志
 root->depth = 0 ;     // 树根深度
 // 对输入的字串循环处理添加进ACTree
 for (i = 0 ; i < npattern ; i++)
 {
  int pat_len ;
  int ch_i ;
  pat_len = (patterns+i)->len ;
  if (pat_len == 0)
  {
   continue ;
  }
  else
  {
   if (pat_len > PATTERN_LEN)
   {
    pat_len = PATTERN_LEN ;
   }
   if (pat_len > max_pattern_len)
   {
    max_pattern_len = pat_len ;
   }
   if (pat_len < min_pattern_len)
   {
    min_pattern_len = pat_len ;
   }
   parent = root ;
   for (ch_i = 0 ; ch_i < pat_len ; ch_i++)
   {
    ch = ((patterns+i)->data)[ch_i] ;
    #ifndef CASE_SENSITIVE
    ch = tolower(ch) ;
    #endif
    // 对应的字符索引为NULL
    if (NULL == parent->childs
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值