BM模式匹配算法图解

合集下载

串匹配BM算法KMP算法BF算法

串匹配BM算法KMP算法BF算法

串匹配BM算法KMP算法BF算法串匹配算法是一种用于在一个主串中查找一个子串的方法。

主串是一个较大的字符串,而子串是一个较小的字符串。

串匹配算法的目的是在主串中找到子串的出现位置或者确定子串不在主串中出现。

三种常见的串匹配算法是BF算法(Brute Force算法),KMP算法(Knuth-Morris-Pratt算法)和BM算法(Boyer-Moore算法)。

1. BF算法(Brute Force算法):BF算法是最简单直观的串匹配算法,也是最基础的算法。

它的思想是从主串的第一个字符开始,逐个与子串进行匹配,如果子串中的所有字符都与主串中的字符相等,则匹配成功;否则,主串向后移动一个位置,子串从头开始重新匹配,直到找到匹配或主串结束。

BF算法的时间复杂度是O(n*m),其中n是主串的长度,m是子串的长度。

在最坏情况下,需要完全比较所有字符。

2. KMP算法(Knuth-Morris-Pratt算法):KMP算法是一种改进的串匹配算法,它利用已经匹配过的部分信息来避免不必要的字符比较,从而提高匹配效率。

KMP算法的核心思想是构建一个next数组,该数组存储了在子串中,在一些字符之前具有相同前缀和后缀的最大长度。

KMP算法在匹配过程中,主串和子串的指针分别从头开始遍历。

如果当前字符匹配成功,则两个指针同时后移;如果匹配失败,则利用next 数组的信息将子串的指针向后移动到一个合适的位置继续匹配。

KMP算法的时间复杂度是O(n+m),其中n是主串的长度,m是子串的长度。

它通过构建next数组,避免了不必要的字符比较,提高了匹配效率。

3. BM算法(Boyer-Moore算法):BM算法是一种基于启发式的串匹配算法,它通过利用模式串的特点,在匹配过程中跳跃性地移动主串的指针,从而提高匹配效率。

BM算法的核心思想是从模式串的末尾到开头进行匹配,并根据不匹配字符的位置进行跳跃。

BM算法分为两个主要步骤:坏字符规则和好后缀规则。

BF算法KMP算法BM算法

BF算法KMP算法BM算法

BF算法KMP算法BM算法BF算法(Brute-Force算法)是一种简单直接的字符串匹配算法。

它的基本思想是从主串的第一个字符开始,逐个与模式串的字符进行比较,如果匹配失败,则主串的指针向右移动一位,继续从下一个字符开始匹配。

重复这个过程,直到找到匹配的子串或者主串遍历完毕。

BF算法的时间复杂度是O(n*m),其中n和m分别是主串和模式串的长度。

当模式串较长时,算法的效率较低。

但是BF算法的实现简单,易于理解,对于较短的模式串和主串,仍然是一种可行的匹配算法。

KMP算法(Knuth-Morris-Pratt算法)是一种改进的字符串匹配算法,它利用了模式串内部的信息,避免了不必要的比较。

KMP算法引入了一个next数组,用于记录模式串中每个位置对应的最长可匹配前缀子串的长度。

KMP算法的基本思想是,当匹配失败时,不是简单地将主串指针右移一位,而是利用next数组将模式串的指针向右移动若干位,使得主串和模式串中已经匹配的部分保持一致,减少比较次数。

通过预处理模式串,计算出next数组,可以在O(n+m)的时间复杂度内完成匹配。

BM算法(Boyer-Moore算法)是一种高效的字符串匹配算法,它结合了坏字符规则和好后缀规则。

BM算法从模式串的末尾开始匹配,根据坏字符规则,如果在匹配过程中发现了不匹配的字符,可以直接将模式串向右滑动到该字符在模式串中最右出现的位置。

BM算法还利用了好后缀规则,当发现坏字符后,可以根据好后缀的位置和模式串的后缀子串进行匹配,从而减少不必要的比较。

通过预处理模式串,计算出坏字符规则和好后缀规则对应的滑动距离,可以在最坏情况下实现O(n/m)的时间复杂度。

总结来说,BF算法是一种简单直接的字符串匹配算法,适用于较短的模式串和主串;KMP算法通过预处理模式串,利用next数组减少比较次数,提高了匹配效率;BM算法结合了坏字符规则和好后缀规则,利用了更多的信息,是一种高效的字符串匹配算法。

BM算法详解

BM算法详解

BM算法详解BM算法 后缀匹配,是指模式串的⽐较从右到左,模式串的移动也是从左到右的匹配过程,经典的BM算法其实是对后缀蛮⼒匹配算法的改进。

为了实现更快移动模式串,BM算法定义了两个规则,好后缀规则和坏字符规则,如下图可以清晰的看出他们的含义。

利⽤好后缀和坏字符可以⼤⼤加快模式串的移动距离,不是简单的++j,⽽是j+=max (shift(好后缀), shift(坏字符)) 先来看如何根据坏字符来移动模式串,shift(坏字符)分为两种情况:坏字符没出现在模式串中,这时可以把模式串移动到坏字符的下⼀个字符,继续⽐较,如下图:坏字符出现在模式串中,这时可以把模式串第⼀个出现的坏字符和母串的坏字符对齐,当然,这样可能造成模式串倒退移动,如下图: 此处配的图是不准确的,因为显然加粗的那个b并不是”最靠右的”b。

⽽且也与下⾯给出的代码冲突!我看了论⽂,论⽂的意思是最右边的。

当然了,尽管⼀时⼤意图配错了,论述还是没有问题的,我们可以把图改正⼀下,把圈圈中的b改为字母f就好了。

接下来的图就不再更改了,⼤家⼼⾥有数就好。

为了⽤代码来描述上述的两种情况,设计⼀个数组bmBc['k'],表⽰坏字符‘k’在模式串中出现的位置距离模式串末尾的最⼤长度,那么当遇到坏字符的时候,模式串可以移动距离为: shift(坏字符) = bmBc[T[i]]-(m-1-i)。

如下图: 数组bmBc的创建⾮常简单,直接贴出代码如下:1 void preBmBc(char *x, int m, int bmBc[]) {23 int i;45 for (i = 0; i < ASIZE; ++i)67 bmBc[i] = m;89 for (i = 0; i <= m - 1; ++i)1011 bmBc[x[i]] = m - i - 1;1213 } 代码分析:ASIZE是指字符种类个数,为了⽅便起见,就直接把ASCII表中的256个字符全表⽰了,哈哈,这样就不会漏掉哪个字符了。

BM立体匹配算法的参数详解

BM立体匹配算法的参数详解

BM立体匹配算法的参数详解1. 最小视差(Minimum Disparity):表示在计算深度图时允许的最小视差值,即物体最近处的深度差异。

选择合适的最小视差值对于过滤无意义的区域非常重要。

2. 最大视差(Maximum Disparity):表示在计算深度图时允许的最大视差值,即物体最远处的深度差异。

选择合适的最大视差值可以防止视差计算的误差。

3. 视差窗口大小(Disparity Window Size):表示计算每个像素的视差时,使用的窗口大小。

较大的窗口尺寸可以提供更准确的深度信息,但也会增加计算时间。

通常情况下,窗口大小是一个奇数,最常见的是3、5或74. 匹配代价度量(Matching Cost Metric):用于计算两个像素之间的匹配代价的度量方法。

最常见的度量方法是灰度差异和绝对差异,也可以根据特定的应用选择适当的度量方法。

5. 匹配代价聚合(Matching Cost Aggregation):用于减少匹配代价图像中的噪声和不一致性的技术。

常用的方法包括平均代价和双边滤波。

6. 视差图优化(Disparity Map Optimization):通过优化视差图像,减少错误匹配和噪声,并提高深度估计的准确性。

常用的方法包括视差图扩张、视差图填充和视差图平滑。

7. 左右一致性检查(Left-Right Consistency Check):用于消除左右图像之间不一致匹配的误差。

该步骤通过检查左右视图之间的匹配来得到更准确的视差图。

8. 剔除无效区域(Invalid Region Exclusion):根据特定应用需求,去除由于遮挡、反射等原因导致的无效区域。

可以使用其他传感器信息或额外的图像处理技术来实现。

9. 空洞填充(Occlusion Filling):通过使用图像分割或插值算法填充由遮挡产生的空洞。

这可以提供更完整和连贯的深度图像。

10. 算法效率(Algorithm Efficiency):BM算法的计算效率对于实时应用很重要。

最详细最容易理解的BM算法简介PPT共37页

最详细最容易理解的BM算法简介PPT共37页

• Shift = 6
-2
Case 2a
• 坏字符在模式串中
• *******NLE********
• NEEDLE

NEEDLE
• Shift =最右的坏字符位置–position(坏)
• Shift = 5
-2
Case 2b
• 坏字符在模式串中
• *******ELE********

NEEDLE
好后缀算法
• 模式串中没有子串匹配上好后缀,并且在 模式串中找不到最长前缀,让该前缀等于 好后缀的后缀时
• S= *******BABCDE******** • T= AACDEFGBCDE
好后缀算法
• 模式串中没有子串匹配上好后缀,并且在 模式串中找不到最长前缀,让该前缀等于 好后缀的后缀时
• S= *******BABCDE********
}
预处理-坏字符
• void preBmBc(char *S, int m, int bmBc[]) { int i; for (i = 0; i < ASIZE; ++i) //ASIZE=256 bmBc[i] = m; for (i = 0; i <=m - 1; ++i) bmBc[S[i]] = m - i - 1;
} • 这是会有倒退的算法设计,优点在于能够
对模式串预处理
预处理-坏字符
• void preBmBc(char *S, int m, int bmBc[]) { int i;
for (i = 0; i < ASIZE; ++i) //ASIZE=256
bmBc[i] = m;

BM算法

BM算法

1.简单的字符串匹配算法
模式匹配问题的简单直接算法是,将 其看成是以模式作为关键字的查找问题, 它将长度为n的正文T划分为n-m+1个长度为 m的子字符串,检查比较每个这样的子串是 否于长度为m的模式p相匹配。
2.boyer-moore串匹配算法
• 算法主要是采用试控法来减少模式串与文 本串的字符比较次数,也就是说,算法在 沿着文本串进行匹配时,利用已知的模式 串的信息跳过一些没有必要的比较。算法 的实现分为两个步骤:
每次比较从↓开始,从右至左移动。
2.boyer-moore串匹配算法
匹配比较过程中,不少情形是前面的许多 字符都匹配而最后的若干个字符不匹配,这时 若采取从左到右的方式扫描的话将浪费很多时 间,因此改为自右至左的方式扫描模式和正文, 这样,一旦发现当正文中出现模式中没有的字 符时就可以将模式、正文大幅度地“滑过”一 段距离。
几种பைடு நூலகம்要的模式匹配算法
在对数据包的有效载荷进行攻击检测时, 对数据包的载荷进行攻击检测的过程从本质上 讲就是一个字符串的模式匹配过程。 对数据包有效载荷进行攻击检测的速度已 经成为最制约网络级入侵检测效率的瓶颈,所 以如何为数据包有效载荷攻击检测过程找到一 种快速有效实用的模式匹配方法是当前网络级 入侵检测系统面临的一个重要问题。
坏字符启发示例2
移动前: 模式串:-> one plus two 文本串:-> two plus three equals five
移动后: 模式串:-> 文本串:-> one plus two two plus three equals five
每次比较从↓开始,从右至左移动。
好后缀启发示例
移动前: 模式串:-> two plus two 文本串:-> count to two hundred thirty 移动后: 模式串:-> 文本串:-> two plus two count to two hundred thirty

BM算法原理图示详细讲解

BM算法原理图示详细讲解

A
B
C
E
C
A
B
E
… …
… …
P
A
B
C
A
B
2010/10/29 于 HoHai University 4216
BM 算法详细图解 编著:WeiSteve@ 自此,讲解完毕。
[Weisteven]
在 BM 算法匹配的过程中,取 Jump(x)与 Shift(x)中的较大者作为跳跃的距离。 BM 算法预处理时间复杂度为 O(m+s),空间复杂度为 O(s),s 是与 P, T 相关的 有限字符集长度,搜索阶段时间复杂度为 O(m*n)。 最好情况下的时间复杂度为 O(n/m),最坏情况下时间复杂度为 O(m*n)。
T
A
B
C
B
A
D
F
T
B
C
F
A
Q
P
C
B
C
A
B
C
E
A
B
C
例二(说明情况 b):
T
A
B
C
B
A
D
F
T
B
C
F
A
Q
P
B
C
C
A
B
C
E
T
B
C
共同后缀为 TBC,寻找 P 中未匹配部分中是否出现过 TBC。发现未曾出现过。 那么我们就要找 P 的最长前缀同时又是 TBC 的最大后缀的情况。 发现只有 BC,那么 P 需要移动前缀 BC 至对齐 T 中的 BC。
A A
B B
C
A
B
由于 CAB 在前面 P 中未曾出现过,只能进行第二种情况的最大前缀的匹配。 上图中对应的就是已经匹配的部分 CAB 字段在 P 中前方的最大重叠 AB。 看出来了吧,最大的移动就是让 P 中的其实部分 AB 跟 T 中已匹配的字段 CAB 的 部分进行对齐。 移动后的结果如下:

【字符串匹配】BM(Boyer-Moore)字符串匹配算法详解总结(附C++实现代码)

【字符串匹配】BM(Boyer-Moore)字符串匹配算法详解总结(附C++实现代码)

【字符串匹配】BM(Boyer-Moore)字符串匹配算法详解总结(附C++实现代码)BM算法思想的本质上就是在进⾏模式匹配的过程中,当模式串与主串的某个字符不匹配的时候,能够跳过⼀些肯定不会匹配的情况,将模式串往后多滑动⼏位。

BM算法寻找是否能多滑动⼏位的原则有两种,分别是坏字符规则和好后缀规则。

坏字符规则:我们从模式串的末尾往前倒着匹配,当我们发现某个字符⽆法匹配时,我们把这个⽆法匹配的字符叫做坏字符(主串中的字符)。

此时记录下坏字符在模式串中的位置si,然后拿坏字符在模式串中查找,如果模式串中并不存在这个字符,那么可以将模式串直接向后滑动m位,如果坏字符在模式串中存在,则记录下其位置xi,那么模式串向后移动的位数就是si-xi,(可以在确保si>xi,执⾏减法,不会出现向前移动的情况)。

如果坏字符在模式串中多次出现,那我们在计算xi的时候,选择最靠后的那个,这样不会因为让模式串滑动过多,导致本来可能匹配的情况被略过。

好后缀规则:在我们反向匹配模式串时,遇到不匹配时,记录下当前位置j位坏字符位置。

把已经匹配的字符串叫做好后缀,记作{u}。

我们拿它在模式串中查找,如果找到了另⼀个跟{u}相匹配的字串{u*},那么我们就将模式串滑动到字串{u*}与主串{u}对齐的位置。

如下图所⽰:如果在模式串中找不到另⼀个等于{u}的⼦串,我们就直接将模式串滑动到主串中{u}的后⾯,因为之前的任何⼀次往后滑动,都没有匹配主串中{u}的情况。

但是这种滑动做法有点太过头了,可以看下⾯的例⼦,如果直接滑动到好后缀的后⾯,可能会错过模式串与主串可以匹配的情况。

如下图:当模式串滑动到前缀与主串中{u}的后缀有部分重合的时候,并且重回部分相等的时候,就可能会存在完全匹配的情况。

所以针对这种情况我们不仅要看好后缀在模式串中,是否有另⼀个匹配的字串,我们还要考察好后缀的后缀字串是否存在跟模式串的前缀字串匹配的情况。

如下图所⽰:最后总结如何确定模式串向后滑动的位数,我们可以分别计算好后缀和坏字符往后滑动的位数,然后取两个数中最⼤的。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Boyer-Moore 经典单模式匹配算法BM模式匹配算法-原理(图解)由于毕业设计(入侵检测)的需要,这两天仔细研究了BM模式匹配算法,稍有心得,特此记下。

首先,先简单说明一下有关BM算法的一些基本概念。

BM算法是一种精确字符串匹配算法(区别于模糊匹配)。

BM算法采用从右向左比较的方法,同时应用到了两种启发式规则,即坏字符规则和好后缀规则,来决定向右跳跃的距离。

BM算法的基本流程: 设文本串T,模式串为P。

首先将T与P进行左对齐,然后进行从右向左比较,如下图所示:若是某趟比较不匹配时,BM算法就采用两条启发式规则,即坏字符规则和好后缀规则,来计算模式串向右移动的距离,直到整个匹配过程的结束。

下面,来详细介绍一下坏字符规则和好后缀规则。

首先,诠释一下坏字符和好后缀的概念。

请看下图:图中,第一个不匹配的字符(红色部分)为坏字符,已匹配部分(绿色)为好后缀。

1)坏字符规则(Bad Character):在BM算法从右向左扫描的过程中,若发现某个字符x不匹配,则按如下两种情况讨论:i. 如果字符x在模式P中没有出现,那么从字符x开始的m个文本显然不可能与P匹配成功,直接全部跳过该区域即可。

ii. 如果x在模式P中出现且出现次数>=1,则以该字符所在最右边位置进行对齐。

用数学公式表示,设Skip(x)为P右移的距离,m为模式串P的长度,max(x)为字符x在P中最右位置。

可以总结为字符x出现与否,将max(x)=0作为初值即可。

例1:下图红色部分,发生了一次不匹配。

计算移动距离Skip(c) = m-max(c)=5 - 3 = 2,则P向右移动2位。

移动后如下图: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)。

以上过程有点抽象,所以我们继续图解。

例2:下图中,已匹配部分cab(绿色)在P中再没出现。

再看下图,其后缀T'(蓝色)与P中前缀P'(红色)匹配,则将P'移动到T'的位置。

移动后如下图:自此,两个规则讲解完毕。

在BM算法匹配的过程中,取SKip(x)与Shift(j)中的较大者作为跳跃的距离。

BM算法预处理时间复杂度为O(m+s),空间复杂度为O(s),s是与P, T 相关的有限字符集长度,搜索阶段时间复杂度为O(m·n)。

最好情况下的时间复杂度为O(n/m),最坏情况下时间复杂度为O(m·n)。

BM模式匹配算法-实现(C语言)下面是SNORT2.7.0中提取出的代码。

1./*2.函数:int* MakeSkip(char *, int)3.目的:根据坏字符规则做预处理,建立一张坏字符表4.参数:5. ptrn => 模式串P6. PLen => 模式串P长度7.返回:8. int* - 坏字符表9.*/10.int* MakeSkip(char *ptrn, int pLen)11.{12. int i;13. //为建立坏字符表,申请256个int的空间14. /*PS:之所以要申请256个,是因为一个字符是8位,15. 所以字符可能有2的8次方即256种不同情况*/16. int *skip = (int*)malloc(256*sizeof(int));17.18. if(skip == NULL)19. {20. fprintf(stderr, "malloc failed!");21. return 0;22. }23.24. //初始化坏字符表,256个单元全部初始化为pLen25. for(i = 0; i < 256; i++)26. {27. *(skip+i) = pLen;28. }29.30. //给表中需要赋值的单元赋值,不在模式串中出现的字符就不用再赋值了31. while(pLen != 0)32. {33. *(skip+(unsigned char)*ptrn++) = pLen--;34. }35.36. return skip;37.}38.39.40./*41. 函数:int* MakeShift(char *, int)42. 目的:根据好后缀规则做预处理,建立一张好后缀表43. 参数:44. ptrn => 模式串P45. PLen => 模式串P长度46. 返回:47. int* - 好后缀表48.*/49.int* MakeShift(char* ptrn,int pLen)50.{51. //为好后缀表申请pLen个int的空间52. int *shift = (int*)malloc(pLen*sizeof(int));53. int *sptr = shift + pLen - 1;//方便给好后缀表进行赋值的指标54. char *pptr = ptrn + pLen - 1;//记录好后缀表边界位置的指标55. char c;56.57. if(shift == NULL)58. {59. fprintf(stderr,"malloc failed!");60. return 0;61. }62.63. c = *(ptrn + pLen - 1);//保存模式串中最后一个字符,因为要反复用到它64.65. *sptr = 1;//以最后一个字符为边界时,确定移动1的距离66.67. pptr--;//边界移动到倒数第二个字符(这句是我自己加上去的,因为我总觉得不加上去会有BUG,大家试试“abcdd”的情况,即末尾两位重复的情况)68.69. while(sptr-- != shift)//该最外层循环完成给好后缀表中每一个单元进行赋值的工作70. {71. char *p1 = ptrn + pLen - 2, *p2,*p3;72.73. //该do...while循环完成以当前pptr所指的字符为边界时,要移动的距离74. do{75. while(p1 >= ptrn && *p1-- != c);//该空循环,寻找与最后一个字符c匹配的字符所指向的位置76.77. p2 = ptrn + pLen - 2;78. p3 = p1;79.80. while(p3 >= ptrn && *p3-- == *p2-- && p2 >= pptr);//该空循环,判断在边界内字符匹配到了什么位置81.82. }while(p3 >= ptrn && p2 >= pptr);83.84. *sptr = shift + pLen - sptr + p2 - p3;//保存好后缀表中,以pptr所在字符为边界时,要移动的位置85. /*86. PS:在这里我要声明一句,*sptr = (shift + pLen - sptr) + p2 - p3;87. 大家看被我用括号括起来的部分,如果只需要计算字符串移动的距离,那么括号中的那部分是不需要的。

88. 因为在字符串自左向右做匹配的时候,指标是一直向左移的,这里*sptr保存的内容,实际是指标要移动89. 距离,而不是字符串移动的距离。

我想SNORT是出于性能上的考虑,才这么做的。

90. */91.92. pptr--;//边界继续向前移动93. }94.95. return shift;96.}97.98.99./*100.函数:int* BMSearch(char *, int , char *, int, int *, int *)101.目的:判断文本串T中是否包含模式串P102.参数:103. buf => 文本串T104. blen => 文本串T长度105. ptrn => 模式串P106. PLen => 模式串P长度107. skip => 坏字符表108. shift => 好后缀表109.返回:110. int - 1表示成功(文本串包含模式串),0表示失败(文本串不包含模式串)。

111.*/112.int BMSearch(char *buf, int blen, char *ptrn, int plen, in t *skip, int *shift)113.{114.int b_idx = plen;115. if (plen == 0)116. return 1;117. while (b_idx <= blen)//计算字符串是否匹配到了尽头118. {119.int p_idx = plen, skip_stride, shift_stride; 120. while (buf[--b_idx] == ptrn[--p_idx])//开始匹配121. {122. if (b_idx < 0)123. return 0;124. if (p_idx == 0)125. {126. return 1;127. }128. }129. skip_stride = skip[(unsigned char)buf[b_idx]];//根据坏字符规则计算跳跃的距离130. shift_stride = shift[p_idx];//根据好后缀规则计算跳跃的距离131. b_idx += (skip_stride > shift_stride) ? skip_stride : shift_stride;//取大者132. }133. return 0;134.}经典单模式匹配算法:KMP、BM;经典多模式匹配算法:AC、Wu-Manber。

貌似实用中,KMP跟C库strstr()效率相当,而BM能快上3x-5x。

于是小女不才花了小天的功夫来研究这个BM算法。

BM如何快速匹配模式?它怎么跳跃地?我今儿一定要把大家伙儿讲明白了,讲不明白您佬跟帖,我买单,包教包会。

相关文档
最新文档