`
十三月的
  • 浏览: 168326 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

打破思维断层之Boyer-Moore

阅读更多

 

BM算法

 

目的本博客以BM算法为载体,意图在减少思维断层情况下了解算法思想

 

目录

 

  • BM算法的创新之处在于“跳跃式”思维方式
  • BM算法VS KMP算法
  • BM过程展示
  • BM案例分析
  • 代码实现
  • 进一步思考

第一步:BM算法的创新:“跳跃式”思维方式

无论是BF算法、KMP算法或者Shift-And/Or算法,他们都是基于前缀,从前向后来进行匹配。BM算法和它们不同,它是基于后缀,从后向前进行匹配。

然而BM算法(由Robert S. BoyerJ Strother Moore两位共同完成)的创新并不是在于后缀匹配,而是在于通过后缀匹配产生了“跳跃式”的思想。跳跃式思想是来源于字符串的随机性,也就是说这种思维方式其实是利用了字符串本身的特性。

第二步:BM算法  VS  KMP算法

不得不说,KMP算法确实比较漂亮,它的厉害之处在于目标串指针不再进行回溯,使得整个算法效率是线性的。但是考虑到实际运行效果,实在是令人遗憾。

KMP的运行效果,别说和BM相比,恐怕大部分情况下就连最初的BF算法都可能无法抗衡,原因在于KMP算法是在假设单词的构造可以是任意的,甚至可以是abababa这样的,但是现实是我们执行文本搜索中的单词却并没有这样的。这算是一个实验室中理想的算法。

http://people.cs.pitt.edu/~kirk/cs1501/animations/String.html 

可以看一下两者效率的对比很有说服力的。下面我用几张图片说明下

KMP算法:图片中包含模式串和目标串 



 

 

 

 
 上述图片并不是全部,只是为了展示过程。实际上本例中KMP就是这样“一步一步”的走到了最后,由于模式串methods的中没有既是前缀又是后缀的字符串,使得结果和普通的BF算法还慢

BM算法



 

 

 

     
  BM算法是跳跃着前进的。

第三步:BM过程展示

BM算法实施方法是从后向前进行匹配。我们先来见证一下这种方法的威力。

 

此处采用作者论文中的例子:

 

从模式串最后一个字符开始匹配,发现FT不匹配,除此之外,F在模式串AT-THAT中根本就不存在,这个意味着匹配的可能性为0.我们可以直接跳过前7个字符。

 
我们只是添加了一个判断,效率瞬间提高很多。这个和BFKMP有什么不同呢?这两种算法,目标串的指针i总是以一步一步的前进,而BM则并没有采用这种方式,它可以一下子增加7(本例),这就是跳跃式思维的表现形式,这个更接近人的思维方式。(下面会有更深入层次的分析前缀匹配和后缀的匹配差异)

BM算法采用了两种启发性的规则:坏字符规则和好后缀规则,决定跳跃的距离

 

1) 坏字符规则(Bad Character

 

  在BM算法从后向前扫描的过程中,若已经有m个字符匹配成功,第m+1个字符X(从后向前)匹配失败,则按下面两种情况讨论:

 

   a)如果字符x在模式P中没有出现,直接全部跳过该区域。

 

   b)如果字符x在模式P中出现,则以该字符进行对齐。

       
我们其实已经见识过a)这个规则,就是上面的例子。

 

2)好后缀规则(Good Suffix

 

BM算法从后向前扫描的过程中,若已经有m个字符匹配成功,第m+1个字符X(从后向前)匹配失败,则按下面两种情况讨论:

 

 a) 如果已经匹配的m个字符,在模式串其他位置也出现过记为m’,则将m’和这m个字符对齐。


     
b) 如果a)中所说情况没有出现,此时需要检查模式串P,若P存在最长前缀s 同时也是P的后缀,则将sP对应的后缀对齐。

 



 
上述两个好后缀规则中取最小的一个移动。

 

其实,在好后缀规则中,如果第一条成立其实就不用检查第二条,因为第二条如果存在,移动距离肯定比第一条大。但是如果第一条不成立,意味着移动距离是模式串P的长度,此时需要检查第二条,如果第二条成立,则安全移动的距离便变小了。

 

第四步:BM案例分析

 

 

 

 

 
 第五步:代码实现

 

 

 

// 匹配算法
	public static int indexOf(char[] ocean, char[] needle) {
		if (needle.length == 0) {
			return 0;
		}
		int charTable[] = makeCharTable(needle);
		int offsetTable[] = makeOffsetTable(needle);
		for (int i = needle.length - 1, j; i < ocean.length;) {
			for (j = needle.length - 1; needle[j] == ocean[i]; --i, --j) {
				if (j == 0) {
					return i;
				}
			}
			// offsetTable根据已经匹配的好后缀的长度取数据 charTable根据坏字符取数据
			i += Math.max(offsetTable[needle.length - 1 - j],
					charTable[ocean[i]]);
		}
		return -1;
	}

	/**
	 * 坏字符规则表
	 */
	private static int[] makeCharTable(char[] needle) {
		final int ALPHABET_SIZE = 256;
		int[] table = new int[ALPHABET_SIZE];
		// 初始化赋值
		for (int i = 0; i < table.length; ++i) {
			table[i] = needle.length;
		}
		// 重新赋值
		for (int i = 0; i < needle.length - 1; ++i) {
			table[needle[i]] = needle.length - 1 - i;
		}
		return table;
	}

	/**
	 * 好后缀规则表 ,
	 * 根据好后缀长度取需要移动的位置 
	 * 由于规则b的值>=规则a的值(始终)
	 *  先根据规则b进行赋值
	 *  再根据好后缀规则a重新赋值
	 */
	private static int[] makeOffsetTable(char[] needle) {
		int[] table = new int[needle.length];
		int lastPrefixPosition = needle.length;
		// 根据好后缀规则b)初始化好后缀表
		for (int i = needle.length - 1; i >= 0; --i) {
			if (isPrefix(needle, i + 1)) {
				lastPrefixPosition = i + 1;
			}
			table[needle.length - 1 - i] = lastPrefixPosition - i
					+ needle.length - 1;
		}
		// 再根据好后缀规则a)重新赋值
		for (int i = 0; i < needle.length - 1; ++i) {
			int slen = suffixLength(needle, i);
			table[slen] = needle.length - 1 - i + slen;
		}
		return table;
	}

	/**
	 * 判断从p开始到结束是否既是后缀同时是前缀 abacactttabac 例如p=9(从左到右,字符a处)结果是true(abac == abac)
	 */
	private static boolean isPrefix(char[] needle, int p) {
		for (int i = p, j = 0; i < needle.length; ++i, ++j) {
			if (needle[i] != needle[j]) {
				return false;
			}
		}
		return true;
	}

	/**
	 * 获取从p到0位置 的最大的是后缀的字串大小 ababactttabac 例如当p=5(c处),结果是abac的大小4
	 */
	private static int suffixLength(char[] needle, int p) {
		int len = 0;
		for (int i = p, j = needle.length - 1; i >= 0 && needle[i] == needle[j]; --i, --j) {
			len += 1;
		}
		return len;
	}

 第六步:进一步思考

 

如果你对BF或者KMP有了解,可以看一下下面的分析,如果没有可以直接跳过,该分析是为了增加对前缀、后缀匹配以及跳跃性分析的了解。

 

也许你可能有疑问,难道前缀匹配就不能这样吗?假设从第一个字符WA开始匹配,W在模式串中也不存在,但是此时却只能跳过1个。

 

当然,BM也可能出现很差的情况。假设已经7个中已经匹配6个,最后一个不同,假设这个时候模式串向后移动1位,那么目标串指针i相当于在比较了次之后,也只是前进了1步。

 

而在前缀匹配中我们也可以实施这样一个检查,当匹配失败的时候,检查模式串前面几个字符是否包含目标串当前匹配失败的字符,如果没有,我们也可以直接跳过这几个已经匹配的字符。

 

那么BM算法为什么不使用前缀匹配呢?我们可以这样理解,在后缀匹配中第1个字符,像上个例子F在模式串中不存在,意味着可以直接跳过前7个字符,当然如果使用前缀匹配,也可以出现这种情况,当匹配了6个字符后,第7个不同,而且第7个字符很生僻如X,前6个中没有X,这个时候我们可以跳过,但是前提是我们已经进行了6次比较,而后缀匹配只是进行了1次,这就是差异。而平时使用的文本搜索更是将后缀匹配效果进行了放大,即平常文本搜索很少会出现共有7个字符,有6个一样,第7个不一样,即使是存在这样的单词,但是你见过这种单词在同一个文本中扎堆出现吗?也许有,那就算你倒霉了。这其实是基于概率的,对文本进行了粗略的概率估计。

 

实际上BM算法并非是最快的算法,但是它实现了思维方式的改变,SundayHorspool对该算法进行了简化,效率更高。

 

  

 

 

  • 大小: 6.4 KB
  • 大小: 6.4 KB
  • 大小: 6.4 KB
  • 大小: 6.4 KB
  • 大小: 6.8 KB
  • 大小: 6.5 KB
  • 大小: 6.5 KB
  • 大小: 6.5 KB
  • 大小: 6.7 KB
  • 大小: 5 KB
  • 大小: 5.2 KB
  • 大小: 97.1 KB
  • 大小: 91.3 KB
  • 大小: 92 KB
  • 大小: 6.5 KB
  • 大小: 6.4 KB
  • 大小: 8.8 KB
  • 大小: 8.9 KB
  • 大小: 5.9 KB
2
2
分享到:
评论

相关推荐

    boyer-moore算法C实现

    Boyer-Moore算法是一种高效的字符串搜索算法,由Robert S. Boyer和J Strother Moore在1977年提出。它通过充分利用模式串(要查找的字符串)的信息,减少了不必要的字符比较次数,从而提高了搜索效率。在C语言中实现...

    论文研究-一种串匹配的快速Boyer-Moore算法.pdf

    在对经典的Boyer-Moore和Quick Search串匹配算法进行分析的基础上,提出了一种更加快速的串匹配算法Quick Boyer-Moore(QBM)。QBM算法利用当前尝试中的已匹配子串、匹配失败字符信息以及与当前窗口下一个字符的位置...

    Boyer-Moore法实现字符串匹配(java)

    坏字符移动表是Boyer-Moore算法的核心组件之一。该表用于记录模式字符串中每个字符最后出现的位置。通过该表,可以快速跳过不匹配的字符,从而提高字符串匹配的效率。 在java代码中,坏字符移动表的创建方法为`...

    简单的Boyer-Moore算法的实现C#附源码

    Boyer-Moore算法是一种高效的字符串搜索算法,由Robert W. Moore和John E. Boyer在1970年代提出。这个算法的核心思想是利用模式串(待查找的字符串)和文本串(被搜索的字符串)的信息来减少不必要的比较,从而提高...

    boyer-moore算法的c#实现

    Boyer-Moore算法是一种高效的字符串搜索算法,由Robert S. Boyer和J Strother Moore在1970年代提出。它通过充分利用了模式(要查找的子串)和文本(主串)的信息,减少了不必要的字符比较,提高了搜索效率。在C#中...

    比Boyer-Moore更快的字符串查找算法.rar_Boyer Moore_字符串查找_查找算法

    Boyer-Moore算法是其中一种高效的方法,但本话题将探讨比Boyer-Moore更快的字符串查找算法。这些优化算法在保持准确性的同时,通过减少比较次数来提高效率。 Boyer-Moore算法由Robert S. Boyer和J. Strothmann于...

    Boyer-Moore-Horspool-Sunday.rar_Boyer Moore_horspo_horspool_sund

    Boyer-Moore-Horspool-Sunday算法是字符串匹配领域中的一个高效算法,它结合了Boyer-Moore算法、Horspool算法以及Sunday算法的优点,以提高在文本中查找特定模式(子串)的速度。这个算法的主要目标是减少不必要的...

    Boyer-Moore算法

    Boyer-Moore字符串搜索算法。它由Bob Boyer和J Strother Moore设计于1977年。此算法仅对搜索目标字符串(关键字)进行预处理,而非被搜索的字符串。虽然Boyer-Moore算法的执行时间同样线性依赖于被搜索字符串的大小...

    Boyer-Moore字符串搜索算法.ppt

    Boyer-Moore字符串搜索算法.ppt

    cpp代码-boyer-Moore算法实现

    Boyer-Moore算法是一种高效的字符串搜索算法,尤其在处理大量文本时表现出色。这个压缩包文件包含了使用C++语言实现的Boyer-Moore算法的源代码,以及一个可能包含算法解释或使用说明的README.txt文件。接下来,我们...

    字符串匹配的Boyer-Moore算法 - 阮一峰的网络日志1

    Boyer-Moore算法是一种高效的字符串匹配算法,由Robert S.Boyer和J Strother Moore于1977年提出。相比于KMP算法,Boyer-Moore算法在实际应用中更为常见,特别是在文本编辑器的“查找”功能中。它的主要优势在于通过...

    newBM.rar_Boyer Moore_Boyer-Moore算法_boyer

    **博耶-摩尔(Boyer-Moore)算法** 博耶-摩尔算法是一种高效字符串搜索算法,由Robert S. Boyer和J Strother Moore于1977年提出。该算法以其独特的预处理和坏字符规则,显著提高了在大数据集中的搜索效率,尤其是在...

    boyer-moore-string-search:C语言中的Boyer Moore字符串搜索实现

    Boyer-moore-string-search 在C中的实现。 该算法从右到左向后执行匹配,并通过迭代匹配,模式移位,匹配,移位等进行操作。移位量是通过应用以下两个规则来计算的: 不良品格规则良好的后缀规则实际的偏移量是其中...

    一种串匹配的快速Boyer_Moore算法.pdf

    Boyer-Moore (BM) 算法因其高效性而成为串匹配中最著名的算法之一。本文介绍了一种改进的Boyer-Moore算法——QuickBoyer-Moore (QBM),该算法旨在进一步提高串匹配的速度。 #### Boyer-Moore算法简介 Boyer-Moore...

    论文研究-BWTBoyerMoore压缩域搜索算法的研究.pdf

    在分析《论文研究-BWT-Boyer-Moore压缩域搜索算法的研究.pdf》中提供的信息时,我们可以提取出以下IT知识要点: 1. **压缩域搜索算法**: 研究的焦点在于压缩域搜索算法,这是一种旨在对压缩过的文件数据进行有效...

    Boyer-Moore 多数表决算法:Boyer-Moore 多数表决算法-matlab开发

    %% Boyer-Moore 多数投票算法% Boyer-Moore Vote Algorithm 解决了多数票问题% 线性时间 O(n) 和对数空间 O(\log n)。 多数票% 问题是确定在任何给定的选择序列中% 有一个选择出现次数比所有其他选择都多,如果是...

    boyer-moore.zip_Windows编程_Visual_C++_

    【标题】"boyer-moore.zip"是一个与Windows编程相关的压缩文件,它专注于Visual C++环境下的编程实践。这个压缩包包含了一种名为Boyer-Moore算法的实现,这是一种在文本搜索中广泛使用的高效算法。 【描述】中提到...

    Boyer–Moore–Horspool algorithm

    - [Wikipedia - Boyer-Moore string search algorithm](https://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_string_search_algorithm) - [论文 - A Fast String Searching Algorithm]...

    string_match:实现并对比了各类字符串匹配算法,包括Sunday、KMP、Boyer-Moore、horspool

    usage:四种字符串匹配算法的实现(Sunday、KMP、Boyer-Moore、horspool)的测试 各文件说明: search_string.h 头文件,包含了对各个函数的声明; search_string.c 包含了头文件中所有函数的具体实现; search_...

Global site tag (gtag.js) - Google Analytics