字符串与模式匹配算法(五):BMH算法
一、BMH算法介绍
在BM算法的实际应用中,坏字符偏移函数的应用次数要远远超过好后缀偏移函数的应用次数,坏字符偏移函数在匹配过程中起着移动指针的主导作用。在实际匹配过程,只是用坏字符偏移函数也非常有效。1980年,奈杰尔·豪斯普(Nigel Horspool)提出了改进的BM算法,也就是BMH算法。简化了BM算法,执行非常方便,效率也很可观。Boyer-Moore算法使用两种策略来确定不匹配模式的位移:坏字符策略和高端策略。 来自Horspool的想法是仅使用坏字符策略,而不使用导致不匹配的字符,而始终使用文本窗口的匹配的字符。
二、主要思想
Horspool建议仅使用窗口最右边字符的坏字符移位来计算Boyer-Moore算法中的移位。例如:
(a) Boyer-Moore
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | ... |
|---|---|---|---|---|---|---|---|---|---|---|
| a | b | c | a | b | d | a | a | c | b | a |
| b | c | a | a | b | ||||||
| b | c | a | a | b |
(b) Horspool
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | ... |
|---|---|---|---|---|---|---|---|---|---|---|
| a | b | c | a | b | d | a | a | c | b | a |
| b | c | a | a | b | ||||||
| b | c | a | a | b |
观察是上面两个不同算法的例子,后缀ab匹配,比较c-a表示不匹配。 Boyer-Moore算法(a)根据最后一次出现c的坏字符位置的策略确定滑动距离。 Horspool算法(b)根据最后一次出现的b来确定滑动距离,其中在模式的最后位置出现的b不计算在内。
同样在Horspool算法中,最有利的情况是,如果每次第一次比较都发现一个文本字符,而该字符根本不在模式中出现。 然后,该算法仅需要O(n / m)个比较。
坏字符策略所需的出现函数occ与Boyer-Moore算法中的计算略有不同。 对于每个字母字符a,occ(p,a)是它在p0 ... pm-2中最后一次出现的位置;如果根本不出现该字符,则为-1。 因此,不会考虑该模式的最后一个字符pm-1。
occ(text, x) = 2
occ(textet, t) = 3
occ(text, t) = 0
occ(next, t) = -1
这里的occ(textet,t)= 3,因为单词texte中t的最后一次出现在位置3。 此外,由于单词tex中t的最后一次出现在位置0,所以occ(text,t)= 0,最后,因为t根本不在nex中出现,所以occ(next,t)= -1。
给定模式p的出现函数存储在数组occ中,该数组由字母字符索引。 对于每个字符,元素a,occ [a]包含对应的函数值occ(p,a)。
三、BMH算法代码
Horspool算法所用到的坏字符策略
1 /**
2 * 坏字符策略
3 */
4 private void horspoolInitocc() {
5 int j;
6 char a;
7
8 for (a = 0; a < alphabetSize; a++)
9 occ[a] = -1;
10
11 for (j = 0; j < m - 1; j++) {
12 a = p[j];
13 occ[a] = j;
14 }
15 }
分析:预处理阶段为O(m + σ)时间复杂度和O(σ)空间复杂度。
Horspool算法的搜索函数
1 /**
2 * Horspool算法的搜索函数
3 */
4 private void horspoolSearch() {
5 int i = 0, j;
6 while (i <= n - m) {
7 j = m - 1;
8 while (j >= 0 && p[j] == t[i + j]) j--;
9 if (j < 0) report(i);
10 i += m - 1;
11 i -= occ[t[i]];
12 }
13 }
搜索阶段具有二次最坏情况O(mn),但是可以证明,一个文本字符的平均比较数在1σ 和 2 /(σ+ 1)之间。
四、总结
BM算法中的坏字符策略对于σ比较小的来说不是很有效,但适合当σ与模式的长度相比比较大时。当ASCII表和在文本编辑器下进行的常规搜索一样BMH变得非常有用。在实践中,单独使用它会产生非常有效的算法。 Horspool建议仅使用窗口最右边字符的坏字符移位来计算Boyer-Moore算法中的移位。
源代码:
1 package algorithm;
2
3 public class Horspool {
4 private static int alphabetSize = 256;
5 private char[] p, t; // 模式,文本
6 private int m, n; // 模式的长度,文本的长度
7 private int[] occ; // 记录文本字符在模式中的位置
8 private String matches; // 匹配位置
9 private char[] showmatches; // 显示匹配的字符数组
10
11 public Horspool() {
12 occ = new int[alphabetSize];
13 }
14
15 public void search(String tt, String pp) {
16 setText(tt);
17 setPatten(pp);
18 horspoolSearch();
19 }
20
21 /**
22 * 设置文本
23 *
24 * @param tt
25 */
26 private void setText(String tt) {
27 n = tt.length();
28 t = tt.toCharArray();
29 initMatches();
30 }
31
32 /**
33 * 设置模式
34 *
35 * @param pp
36 */
37 private void setPatten(String pp) {
38 m = pp.length();
39 p = pp.toCharArray();
40 horspoolInitocc();
41 }
42
43 /**
44 * 坏字符策略
45 */
46 private void horspoolInitocc() {
47 int j;
48 char a;
49
50 for (a = 0; a < alphabetSize; a++)
51 occ[a] = -1;
52
53 for (j = 0; j < m - 1; j++) {
54 a = p[j];
55 occ[a] = j;
56 }
57 }
58
59 /**
60 * Horspool算法的搜索函数
61 */
62 private void horspoolSearch() {
63 int i = 0, j;
64 while (i <= n - m) {
65 j = m - 1;
66 while (j >= 0 && p[j] == t[i + j]) j--;
67 if (j < 0) report(i);
68 i += m - 1;
69 i -= occ[t[i]];
70 }
71 }
72
73 /**
74 * 初始化匹配位置该显示的数组
75 */
76 private void initMatches() {
77 matches = "";
78 showmatches = new char[n];
79 for (int i = 0; i < n; i++) {
80 showmatches[i] = ' ';
81 }
82 }
83
84 /**
85 * 匹配报告
86 *
87 * @param i
88 */
89 private void report(int i) {
90 matches += i + " ";
91 showmatches[i] = '^';
92 }
93
94 /**
95 * 搜索后返回匹配位置
96 *
97 * @return
98 */
99 public String getMatches() {
100 return matches;
101 }
102
103 /**
104 * BMH测试主函数
105 *
106 * @param args
107 */
108 public static void main(String[] args) {
109 Horspool horspool = new Horspool();
110 String tt, pp;
111 tt = "abcdabcd";
112 pp = "abc";
113 horspool.search(tt, pp);
114 System.out.println(pp);
115 System.out.println(tt);
116 System.out.println(horspool.showmatches);
117 System.out.println(horspool.getMatches());
118 }
119 }
字符串与模式匹配算法(五):BMH算法的更多相关文章
- 常用算法3 - 字符串查找/模式匹配算法(BF & KMP算法)
相信我们都有在linux下查找文本内容的经历,比如当我们使用vim查找文本文件中的某个字或者某段话时,Linux很快做出反应并给出相应结果,特别方便快捷! 那么,我们有木有想过linux是如何在浩如烟 ...
- 字符串与模式匹配算法(二):MP算法
一.MP算法介绍 MP 算法(Morris-Pratt算法)是一种快速串匹配算法,它是詹姆斯·莫里斯(James Morris)和沃恩·普莱特(Vaughan Pratt)在1970年提出的一种快速匹 ...
- 字符串与模式匹配算法(一):BF算法
一.BF算法的基本思想 BF(Brute Force)算法是模式匹配中最简单.最直观的算法.该算法最基本的思想是从主串的第 start 个字符起和模式P(要检索的子串)的第1个字符比较,如果相等,则逐 ...
- 字符串的模式匹配算法——KMP模式匹配算法
朴素的模式匹配算法(C++) 朴素的模式匹配算法,暴力,容易理解 #include<iostream> using namespace std; int main() { string m ...
- 字符串与模式匹配算法(四):BM算法
一.BM算法介绍 BM算法(Boyer-Moore算法)是罗伯特·波义尔(Robert Boyer)和杰·摩尔(J·Moore)在1977年共同提出的.与KMP算法不同的是,BM算法是模式串P由左向右 ...
- 字符串与模式匹配算法(六):Needleman–Wunsch算法
一.Needleman-Wunsch 算法 尼德曼-翁施算法(英语:Needleman-Wunsch Algorithm)是基于生物信息学的知识来匹配蛋白序列或者DNA序列的算法.这是将动态算法应用于 ...
- 字符串模式匹配算法2 - AC算法
上篇文章(http://www.cnblogs.com/zzqcn/p/3508442.html)里提到的BF和KMP算法都是单模式串匹配算法,也就是说,模式串只有一个.当需要在字符串中搜索多个关键字 ...
- 字符串与模式匹配算法(三):KMP算法
一.KMP算法介绍 KMP算法与前面的MP算法一脉相承,都是充分利用先前匹配的过程中已经得到的结果来避免频繁回溯.回顾一下MP算法,如下图的模式串偏移,当前模式字符串P的左端的p0与目标字符串T中tj ...
- 串的模式匹配算法1 BF算法
BF算法 字符串的模式匹配不一定要从主串的第一个位置开始,可以指定主串中查找的起始位置 pos. 2. 算法步骤: 1)分别利用计数器指针 i 和 j 指定主串和模式串即小字符串待比较的位置,初始化为 ...
随机推荐
- weblogic漏洞初探之CVE-2015-4852
weblogic漏洞初探之CVE-2015-4852 一.环境搭建 1. 搭建docker 这里用了vulhub的环境进行修改:https://vulhub.org/ 新建个文件夹,创建两个文件doc ...
- UVA 1599 Ideal Path(双向bfs+字典序+非简单图的最短路+队列判重)
https://vjudge.net/problem/UVA-1599 给一个n个点m条边(2<=n<=100000,1<=m<=200000)的无向图,每条边上都涂有一种颜色 ...
- COS控制台进阶 - 文件预览和在线编辑
导语 | COS控制台新上线了文件预览功能,用户可在控制台内直接预览.编辑文件内容. 前不久,微软发布了 vscode for web 的公告,是基于web的在线代码编辑器,无需下载安装可以直接在we ...
- spring入门3-jdbcTemplate简单使用和声明式事务
1.JdbcTemplate简单使用 1.1.引入相关依赖包 <dependency> <groupId>mysql</groupId> <artifactI ...
- javascript traverse object attributes 遍历对象属性
* for in for (var prop in o) { if (o.hasOwnProperty(prop)) { console.log(o[prop]); } } * Object keys ...
- 《Android自动化环境搭建》
一.安装JDK并配置环境变量 1:在Java官网上下载本机系统相对应的jdk文件安装,直接下一步一步到位 2:配置JAVA_HOME 新建 JAVA_HOME 环境变量,变量值是所安装JDK 的路径, ...
- px em rem区别
国内的设计师大都喜欢用px,而国外的网站大都喜欢用em和rem,那么三者有什么区别,又各自有什么优劣呢? PX特点 1. IE无法调整那些使用px作为单位的字体大小: 2. 国外的大部分网站能够调整的 ...
- 鸿蒙内核源码分析(任务管理篇) | 任务池是如何管理的 | 百篇博客分析OpenHarmony源码 | v5.05
百篇博客系列篇.本篇为: v05.xx 鸿蒙内核源码分析(任务管理篇) | 任务池是如何管理的 | 51.c.h .o 任务管理相关篇为: v03.xx 鸿蒙内核源码分析(时钟任务篇) | 触发调度谁 ...
- Android系统编程入门系列之应用级文件在应用程序间的共享
在上篇文章了解到应用级文件只能被其所创建的应用程序所访问,那么其他应用程序是不是就无论如何都无法访问了呢?肯定不是的,只要文件经过其创建的应用程序授权,还是可以被其他应用程序所访问的.这也就是应用级文 ...
- git批量处理git author和commit
最近在做自己项目的时候,由于使用了git全局配置的用户名和邮箱,导致自己私人的仓库里面的所有提交记录都是用的公司的邮箱和用户名,于是想批量替换一下. 可以在需要修改的项目的根目录下使用如下命令,进行批 ...