AC-BM算法将待匹配的字符串集合转换为一个类似于Aho-Corasick算法的树状有限状态自动机,但构建时不是基于字符串的后缀而是前缀。匹配时,采取自后向前的方法,并借用BM算法的坏字符跳转(Bad Character Shift)和好前缀跳转(Good Prefix Shift)技术。
坏字符跳转即当字符串树中的字符与被匹配内容x失配时,将字符串树跳转到下一个x的出现位置,如果x的字符串树不存在,则将字符串树向左移动字符串树的最小字符串长度。好前缀跳转即当字符串树中的字符与被匹配内容x失配时,将字符串树跳转到字符串树中一个与被测正文部分等同的位置。这个等同部分可以是字符串树中某字符串的子串(子串跳转),也可以是一个字符串的后缀(后缀跳转)。
// 关键字数据结构
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 ;
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 ;
坏字符跳转即当字符串树中的字符与被匹配内容x失配时,将字符串树跳转到下一个x的出现位置,如果x的字符串树不存在,则将字符串树向左移动字符串树的最小字符串长度。好前缀跳转即当字符串树中的字符与被匹配内容x失配时,将字符串树跳转到字符串树中一个与被测正文部分等同的位置。这个等同部分可以是字符串树中某字符串的子串(子串跳转),也可以是一个字符串的后缀(后缀跳转)。
当既有好后缀跳转,又有坏字符跳转时,则判断如果有后缀跳转,就使用好前缀跳转(子串跳转与后缀跳转的最小值);否则,使用好前缀跳转与坏字符跳转的最大值。
具体C实现代码如下:
AC-BM.h文件:
#ifndef _AC_BM_H
#define _AC_BM_H
#define _AC_BM_H
#define PATTERN_LEN 1024
#define MAX_ITEMS 20
#define MAX_ITEMS 20
/// 模式树节点结构
typedef struct _pattern_tree_node
{
int label ; // 标识, -2 根节点, -1 中间节点, n 第n个字串尾节点
int depth ; // 节点深度
unsigned char ch ; // 节点对应的字符
int GSshift ; // 好字串位移
int BCshift ;
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 ;
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) ;
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"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "ac_bm.h"
// 宏定义
//#define CASE_SENSITIVE
//#define DEBUG_SEARCH
//#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)) ;
{
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 ; // 树根深度
root->depth = 0 ; // 树根深度
// 对输入的字串循环处理添加进ACTree
for (i = 0 ; i < npattern ; i++)
{
int pat_len ;
int ch_i ;
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 == 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 ;
}
{
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] ;
for (ch_i = 0 ; ch_i < pat_len ; ch_i++)
{
ch = ((patterns+i)->data)[ch_i] ;
#ifndef CASE_SENSITIVE
ch = tolower(ch) ;
#endif
ch = tolower(ch) ;
#endif
// 对应的字符索引为NULL
if (NULL == parent->childs
if (NULL == parent->childs