BM模式匹配算法原理_第1页
BM模式匹配算法原理_第2页
BM模式匹配算法原理_第3页
BM模式匹配算法原理_第4页
BM模式匹配算法原理_第5页
已阅读5页,还剩8页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、BM模式匹配算法原理(图解) 修改浏览权限 | 删除 首先,先简单说明一下有关BM算法的一些基本概念。BM算法是一种精确字符串匹配算法(区别于模糊匹配)。BM算法采用从右向左比较 的方法,同时应用到了两种启发式规则,即坏字符规则 和好后缀规则 ,来决定向右跳跃的距离。BM算法的基本流程: 设文本串T,模式串为P。首先将T与P进行左对齐,然后进行从右向左比较 ,如下图所示: 若是某趟比较不匹配时,BM算法就采用两条启发式规则,即坏字符规则 和好后缀规则 ,来计算模式串向右移动的距离,直到整个匹配过程的结束。 下面,来详细介绍一下坏字符规则 和好后缀规则 。 首先,诠释一下坏字符和好后缀的概念。

2、请看下图: 图中,第一个不匹配的字符(红色部分)为坏字符,已匹配部分(绿色)为好后缀。 1)坏字符规则(Bad Character): 在BM算法从右向左扫描的过程中,若发现某个字符x不匹配,则按如下两种情况讨论: i. 如果字符x在模式P中没有出现,那么从字符x开始的m个文本显然不可能与P匹配成功,直接全部跳过该区域即可。 ii. 如果x在模式P中出现,则以该字符进行对齐。 用数学公式表示,设Skip(x)为P右移的距离,m为模式串P的长度,max(x)为字符x在P中最右位置。 例1: 下图红色部分,发生了一次不匹配。 计算移动距离Skip(c) = 5 - 3 = 2,则P向右移动2位。

3、移动后如下图: 2)好后缀规则(Good Suffix): 若发现某个字符不匹配的同时,已有部分字符匹配成功,则按如下两种情况讨论: i. 如果在P中位置t处已匹配部分P在P中的某位置t也出现,且位置t的前一个字符与位置t的前一个字符不相同,则将P右移使t对应t方才的所在的位置。 ii. 如果在P中任何位置已匹配部分P都没有再出现,则找到与P的后缀P相同的P的最长前缀x,向右移动P,使x对应方才P后缀所在的位置。 用数学公式表示,设Shift(j)为P右移的距离,m为模式串P的长度,j 为当前所匹配的字符位置,s为t与t的距离(以上情况i)或者x与P的距离(以上情况ii)。 以上过程有点抽象,

4、所以我们继续图解。例2: 下图中,已匹配部分cab(绿色)在P中再没出现。 再看下图,其后缀T(蓝色)与P中前缀P(红色)匹配,则将P移动到T的位置。 移动后如下图: 自此,两个规则讲解完毕。 在BM算法匹配的过程中,取SKip(x)与Shift(j)中的较大者作为跳跃的距离。 BM算法预处理时间复杂度为O(m+s),空间复杂度为O(s),s是与P, T相关的有限字符集长度,搜索阶段时间复杂度为O(mn)。最好情况下的时间复杂度为O(n/m),最坏情况下时间复杂度为O(mn)。(二)所谓精确字符串匹配问题,是在文本 T 中找到所有与查询P 精确匹配的子串。而 BM 算法可以非常有效地解决这个问

5、题,让时间复杂度降到低于线形的水平。 BM 算法主要用了三种巧妙而有效的方法,即从右到左扫描,坏字符规则和好后缀规则。 从右到左扫描的意思是从最后一个字符开始向前匹配,而不是习惯上的从开头向后匹配。 坏字符规则是,从右到左的扫描过程中,发现 Ti 与 Pj 不同,如果P 中存在一个字符 Pk 与 Ti 相同,且 ki 那么就将直接将 P 向右移使 Pk 与 Ti 对齐,然后再从右到左进行匹配。如果 P 中不存在任何与 Ti 相同的字符,则直接将 P 的第一个字符与 Ti 的下一个字符对齐,再从右到左进行比较。 如图: T: a b c b a d f t a t e P: c b a x a

6、d P: c b a x a d 用 R(x) 表示字符 x 在 P 中出现的最右位置,此例中 R(b)=2。 可以看出使用从右到左扫描和坏字符规则可以跳过 T 中的很多位置不去检查,从而使时间复杂度低于线性。 好后缀规则是,从右到左的扫描过程中,发现 Ti 与 Pj 不同,检查一下相同的部分t 是否在 P 中的其他位置 t 出现,a) 如果 t 与 t 的前一个字母不相同,就将 P 向右移,使t 与 T 中的 t 对齐。b) 如果t 没有出现,则找到与t 的后缀相同的 P 的最长前缀 x,向右移动P ,使x 与 T 中t 的后缀相对应。 如图a):N: 1N: 1 2 3 4 5 6 7 8

7、 9 0 1 2 3 4 5 6 7 8 T: a b c b a d f tbcf a q v t b c e. P: c b c a b c e a b c P:c bc a b c e a b c f 可见,并不是将 P 向右移让 P5 与 T9 对齐,而是让 P2 与 T9 对齐,因为 P1 与 P8 不相同。用 L(i) 表示 t 的最大位置,此例中, L(9)= 3。 如图b):N: 1N: 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 T: a b c b a d f tbcf a q v t b c e. P:bc c a b c et b c P:

8、bc c a b c et b c 可见,当 P 向左找不到 “tbc”时,就找到 “tbc”的最长与 P 的前缀匹配的后缀,并将 P 向右移。用l(i) 表示这个最长后缀的长度,这个例子中 i=8。 整个算法是这样的:预处理 输入查询字符串 P, 计算 P 中每个位置的 L(i) 和 l(i),并计算 R(i)。查询 k:=n; / n 是 T 中字符的总数 while k0 and P(i)=T(i) do begin i:=i-1; h:=h-1; end; if i=0 then begin 输出 T 的这个位置上的字符串; k:= k+n-l(2);end else 移动 P(增加

9、k),k 取 好后缀规则和坏字符规则决定的最大值 end; 预处理阶段可以根据上一篇文章提到的 Zbox 方法进行处理,时间复杂度为线性。 整个算法的时间复杂度最坏的情况是 O(m),m 是 T 的长度。(三)BM算法的基本思想是从右向左进行比较。开始时仍是P(Pattern)的最左边与S(String)的最左边对齐,但首先进行Pm与Tm的比较。当某趟比较中出现不匹配时,BM算法采用两条启发性规则计算模式串右移的距离,即坏字符规则和好后缀规则。 1) 坏字符规则(Bad Character) P中的某个字符与T中的某个字符不相同时使用坏字符规则右移模式串P, P右移的距离可以通过delta1函

10、数计算出来。delta1函数的定义如下: delta1(x) = - m; xPj (1 = j = m),即x在P中未出现 | - m - maxk|Pk = x, 1 = k s)在匹配过程中,取delta1和delta2中的大者。BM算法的最坏时间复杂度为O(m*n),但实际比较次数只有文本串长度的20%30%。*BM字符串匹配算法从snort2.2的mstring.c中整理而来*#include #include * 生成skip数组,即delta1数组*int *make_skip(char *ptrn, int plen)int *skip = (int *)malloc(256

11、* sizeof(int);int *sptr = skip + 256;if (skip = NULL) fprintf(stderr, malloc failed!);while (sptr- != skip) *sptr = plen + 1;while (plen != 0) skip(unsigned char)*ptrn+ = plen-;return skip;* 生成shift数组,即delta2数组*int *make_shift(char *ptrn, int plen)int *shift = (int *)malloc(plen * sizeof(int);int *s

12、ptr = shift + plen - 1;char *pptr = ptrn + plen - 1;char c;if (shift = NULL) fprintf(stderr, malloc failed!);c = ptrnplen - 1;*sptr = 1;while (sptr - != shift) char *p1 = ptrn + plen - 2, *p2, *p3; do while (p1 = ptrn & *p1- != c); p2 = ptrn + plen - 2; p3 = p1; while (p3 = ptrn & *p3- = *p2- & p2 =

13、pptr); while (p3 = ptrn & p2 = pptr); *sptr = shift + plen - sptr + p2 - p3; pptr-;return shift;* 搜索函数*int mSearch(char *buf, int blen, char *ptrn, int plen, int *skip, int *shift)int b_idx = plen;if (plen = 0) return 1;while (b_idx = blen) int p_idx = plen, skip_stride, shift_stride; while (buf-b_idx = ptrn-p_idx) if (b_idx shift_stride) ? skip_stride : shift_stride;return 0;int main()char str100 = faecabcxxdefeabcxxxabcdwaw;char pattern10 = abcxxxabc;int *skip, *shift, i;skip = make_skip(pattern, strlen(pattern);shift = make_shift(pattern, strl

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论