概念
horspool算法为字符串匹配算法,这是一个空间换时间的算法,算法把模式和文本的开头字符对齐,从模式的最后一个字符开始比较,如果尝试比较失败了,它把模式向后移。每次尝试过程中比较是从右到左的。我们不会像蛮力法那样移动一格,根据不同情况移动,有以下四种情况

  1. 如果模式中不存在c(在我们的例子中,c就是字母S),模式安全移动的幅度就是他的全部长度
    文本:S0 S1 S2……… D……………………

模式 B A R E B R

移动: B A R B E R

  1. 如果模式中存在c,但它不是模式的最好一个字符(在我们的例子中,c就是字母B),移动时应该把模式中最右边的c和文本中的c对齐:

文本:S0 S1 S2……… B……………………

模式: B A R E B R

移动: B A R B E R

  1. 如果c正好是模式中最后一个字符,但在模式中其他m-1个字符中不包含c,移动情况类似1,移动幅度为m

文本:S0 S1 S2…B R……………………

模式: B A R E B R

移动: B A R B E R

  1. 如果c是模式中的最好一个字符,而且在模式的前m-1个字符中也包含c,移动的情况类似于2:移动时应该把模式中前m-1个字符中的c和文本中的c对齐
    文本:S0 S1 S2.……………… R……………………

模式: B A R E B R

移动: B A R B E R

这说明,比起蛮力算法每次总是移动一个位置,从右到左的字符比较使模式模式移动得更远。然而,如果在每次尝试时都必须检查模式中的每个字符,它的优势也会丧失殆尽。我们可以预先算出遇到某个字符要移动的距离,并把它存在一个表中。具体来说,对于每一个字符c,可以通过以下公式算出移动距离:

算法步骤

  1. 对于给定的长度为m的模式和在模式及文本中用到的字母表,按照上面的描述构造移动表。
  2. 将模式与文本的开始处对齐。
  3. 重复下面的过程,直到发现了一个匹配子串或者模式到达了文本的最后一个字符以外。从模式的最后一个字符开始,比较模式和文本中的相应字符,直到:要么所有m个字符都匹配(然后停止,要么遇到了一对不匹配的字符。在后一种情况下,如果c是当前文本中和模式的最后一个字符相对齐的字符,从移动表的第c列中取出单元格t(c)的值,然后将模式沿着文本向右移动t(c)个字符的距离。

建表算法
ShiftTable(P[0…m-1])
for i <-- 0 to n - 1 do Table[t[i]] <-- m //n表示文本串的长度, t[i]表示文本串
for j <-- 0 to m - 2 do Table[p[j]] <-- m - 1 - j //m表示模式串的长度, p[j]表示模式串
return Table

字符匹配过程算法
HorspoolMatching(p[0…m-1], t[0…n-1])
//输入:模式串p和文本串t
//输出:第一个匹配模式串最左端字符的下标,如果没有匹配模式串,则返回-1
ShifTable(p[0…m - 1]) //生成移动表
i <-- m-1 //模式串最右端位置
while i <= n - 1 do
k<–0 //匹配字符的个数
while k <= m - 1 and p[m - 1 - k] = t[i - k] do
k <-- k + 1
if k = m //如果匹配字符个数与模式串个数相等
return i - m + 1;
else i <-- i + Table[t[i]]
return -1

例题
考虑在一个由英文字母和空格(用下划线表示)构成的文本中查找模式BARBER.

代码

#include<stdio.h>
#include<string.h>
#define max 1000
#define m 10
char mode[max] = {'J', 'I', 'M', '_', 'S', 'A', 'W', '_', 'M', 'E', '_', 'I', 'N', '_', 'A', '_', '_', 'B', 'A', 'R', 'B', 'E', 'R', 'S', 'H', 'O', 'P'};//文本串
char string[m] = {'B', 'A', 'R', 'B', 'E', 'R'}; //模式串
int Table[max]; //移动表 int HorspoolMatching(int a, int b){  /*建表过程*/ //a是模式串的长度,b是文本串的长度 /*Table是一个可能出现的字母表和它对应的应该移动步数,也就是某个字母应该* 移动多少步这么一个表,但并不需要dictionary集合来完成,因为字符都是可以* 转化为ASCALL码的,我们直接用每个不同的下标表示每个字母和符号即可,而值便是* 应该移动的步数*/for(int i = 0; i < b; i++)Table[mode[i]] = a;       //首先移动将表中每个元素都置为m,m就是模式的长度/*移动表此时所以元素的值都是6,但是我们现在需要改变模式* 中那几个字符对应的值,也就是说如果出现模式中的字符,我们* 是不应该移动6格去的,而且模式中有可能出现相同字符的,比如* BARBER,但是horspool算法是从模式右方进行匹配的,所以我们* 赋值的时候应该从左往右去赋值,这样模式中字符对应的移动步数* 的最后一次改写是在该字符最后一次出现的时候*//*Table是char集合,p[i]对应是字母,循环的时候,比如模式* 是BARBER,那么首先string[i]='B',table[B]=6-1-0=5,然后* Table[A]=6-1-1=4;Table[R]=6-1-2=3;然后此时又是计算B了,* 这就是为什么我们这里要从左向右赋值的原因,这样B又被再次赋值,* 而此时的B是离右边最近的,Table[B]=6-1-3=2,Table[E]=6-1-4=1,*/for(int j = 0; j < a - 1; j++)Table[string[j]] = a - 1 - j;  //执行完后此时真正形成一个移动表,表中元素包含全部ACALL码对应的字符,所应该移动的步长/*匹配过程*/int i = a - 1;  //光标先定于模式最后一位int k = 0;  //匹配模式字符串字符个数  while(i < b){k = 0;/*K用来计量此时匹配了几个,K<m则表示此时还没有匹配完,* P[m-1-k]是模式中对应字符,t[i-k]是文本串中对应字符* 如果相同则k++,继续对照前一个*/while(k <= a - 1 && string[a - 1 - k] == mode[i - k]){k++;} if(k == a)   //当匹配个数等于模式串个数,返回下标return i - a + 1;elsei = i + Table[mode[i]];  //否则移动对应的table移动表需要移动的距离}return -1;
}int main(){int index = HorspoolMatching(strlen(string), strlen(mode));printf("模式匹配到的首位置是:%d", index + 1); return 0;
}

运行结果

分析
虽然Horspool算法的最差效率属于O(nm),但对于随即文本来说,它的效率是属于O(n)的。而且,虽然效率类型相同,但平均来说,Horspool算法显然要比蛮力算法快许多。

结尾
写博客是为了一是整理所学知识,亲生写代码的经验,而是为了总结经典算法,三是督促自己努力,懂得越多,越知道自己知识的浅薄,四是希望和他人多多交流,有什么不对的地方大佬们多多指点

Horspool算法相关推荐

  1. C++horspool算法查找字符串是否包含子字符串(附完整源码)

    C++horspool算法查找字符串是否包含子字符串 C++Shorspool算法查找字符串是否包含子字符串完整源码(定义,实现,main函数测试) C++Shorspool算法查找字符串是否包含子字 ...

  2. 时空权衡在模式匹配算法中的应用(JAVA)--Horspool算法(简化版BM算法)

    模式匹配是数据结构中字符串的一种基本运算,给定一个子串,要求在某个字符串中找出与该子串相同的所有子串.假设P是给定的子串,T是待查找的字符串,要求从T中找出与P相同的所有子串,这个问题成为模式匹配问题 ...

  3. 字符串匹配算法:Horspool算法

    Horspool 字符串匹配算法对Boyer-Moore算法的简化算法. Horspool 算法是一种基于后缀匹配的方法,是一种"跳跃式"匹配算法,具有sub-linear亚线性时 ...

  4. horspool算法C语言代码,sfa3

    习题6.1 1. hint sort the list and then simply return the n/2th elements of the sorted list. 效率: 假设排序算法 ...

  5. horspool 算法java实现_关于String里indexOf()的一些思考

    评论 # re: 关于String里indexOf()的一些思考 2010-09-30 11:36 denniis 理论上说简单的匹配算法是O(m*n)的时间复杂度,而KMP可以达到O(m+n),在我 ...

  6. Horspool 字符串快速查找算法

    Horspool算法是后缀搜索算法,对于每个文本搜索窗口,将窗口内的最后一个字符与模式串(needle)的最后一个字符进行比较.如果相等,则继续从后向前验证其他字符,直到完全相等或者某个字符不匹配.当 ...

  7. 通用算法-sql相似度模糊匹配

    1.需求描述:数据库采集sql语句的记录表,包含记录编号-ID.日期时间-data.sql语句-statement,对表内每一条记录的sql语句和表内其他记录的sql语句进行模糊匹配,以顺序字符匹配方 ...

  8. # 字符串从右往左查找_字符串匹配(搜索,查找)算法

    (一)前言 所谓的字符串匹配就是在一个长字符串(可称文本T)中找一个短字符串(可称模式P),看长字符串中是否存在短字符串,若存在则返回出现的第一个位置,若不存在则返回一个标记.字符串搜索算法有很多,比 ...

  9. 模式匹配算法----KMP算法以及next数组的解法

    KMP算法:求字符串匹配(也叫模式匹配)的算法,即给定一个字符串,求其某一子串在其中出现的位置. 普通模式匹配 例如:给定字符串为abcabaaabaabcac,求其子串abaabcac在其中出现的位 ...

  10. C和C++算法完整教程专栏完整目录

    C和C++算法完整教程专栏完整目录 专栏说明如下 完整专栏目录如下 专栏说明如下 内容:C和C++算法完整教程 数量:680篇博文(2023年2月15日截止) 更新时间至:2023年2月15日(后续加 ...

最新文章

  1. 消息中间件消费到的消息处理失败怎么办?
  2. leetcode算法题--礼物的最大价值
  3. BZOJ-1927-星际竞速-SDOI2010
  4. 速度优化_网站打开速度慢?如何优化?
  5. 2015-05-31
  6. CodeForces 297A Parity Game (脑补题)
  7. Android控制WIFI相关操作
  8. eclipse中添加aptana插件(html.css.js自动提示)
  9. 总用量的统计_每月公开使用量!广州市开启机制砂信息采集工作
  10. python3.X出现关于模块(i18n)的不能使用的解决方法
  11. 在VMware安装Windows server 2003步骤
  12. cadlisp框选打印_caD批量打印LISP程序,因为工作需要。只要LISP的。
  13. 螺旋模型 增量模型_螺旋模型| 软件工程
  14. 文献笔记(4)(2018ISSCC 13.3)
  15. 用PHP实现小写金额转换大写金额【精确到分】
  16. 12张图片html代码,利用JS实现多张图片合成一张图片代码
  17. 银行系统日终结算要多久_银行 核心系统的清算与结算 - 系统性能与软件架构 - 51Testing软件测试网 51Testing软件测试网-软件测试人的精神家园...
  18. Flink实操 : 状态管理
  19. Oracle定时任务dbms_scheduler
  20. 基于Java的留言板系统的设计与实现

热门文章

  1. AI创作现状与未来发展浅析
  2. CAN、CAN FD
  3. 提示参数错误html页面,网页上有错误怎么修复提示参数错误
  4. 生意参谋活动复盘分析
  5. 数学建模相关比赛汇总(含各赛事官方网站链接)
  6. C语言作业NOTES
  7. 使用JPA @OneToMany关联时,@ JoinColumn和mappedBy有什么区别
  8. 内存映射文件mmap
  9. 破解密码——利用Windows PE操作系统破解Windows PIN
  10. 再多的非标电气设计也不怕了