当前课程知识点:数据结构(下) > 第十一章 串(下) > (e1)BM_GS算法:好后缀 > 11e1-1: 兼顾经验
以上介绍的bc策略
并非BM算法家庭中的唯一成员
它还有一个名为gs的好兄弟
也就是所谓的好后缀策略
gs策略的作用与bc策略恰好互补
它着眼于充分利用此前的比对所提供的经验
我们首先来通过一个实例来看看
bc策略为什么没能有效地利用经验
而如果能利用经验
我们又能做得多好
来看这样一个文本串
其中标注为x的字符内容都是无所谓的
接下来是我们的模式串
假设按照常规
我们首先将它们在首字符处对齐
然后按照BM算法的策略
从末字符开始比对
可以看到 第一次比对成功
第二次比对也成功
实际上 我们会经过4次成功的比对
直到C和H失配
此时的H
就是所谓的坏字符
为了与主串中的C相配
我们接下来应该尽可能地在模式串中
找到字符C
并试图与之对齐
然而尽管这里总共有3个C
你应该记得 我们最终选用的应该是最靠右侧的那个
然而很遗憾
最右端的这个C 位置过于靠右
以至于 如果我们需要将它与文本串中的这个C对齐
将会导致整个模式串的左移
而不是右移
你应该记得
bc策略在此时会如何处置
没错 它会简明地让模式串向右侧移动一个字符
接下来 继续从末字符开始
启动新一轮的扫描比对
可以看到 这一轮比对在经过了一次成功之后
将会再一次地失败于H和C的失配
此时的坏字符为C
于是接下来
bc策略为了能够使得文本串中失配的这个H
能够恢复匹配
将会在模式串中找出某个H
并试图将其与文本串中的H对齐
从而使这个H能够得到匹配
然而刚才的那个特殊情况又再一次出现了
因为我们注意到 模式串的这3个H中
最靠后的这个H 同样过于靠后
从而使得 如果将它与文本串中的这个H对齐
将同样会导致模式串的左移而不是右移
可想而知
bc策略在此时将如何处理
没错
依然是将模式串向后移动一个字符
然后再一次地从末字符开始
启动新一轮的比对
这一回
第一次比对即告失败
于是 bc策略同样会试图从模式串中找出一个适当的A
并试图将它与文本串中的A对齐
从而使得这个A能够得以匹配
这一回我们的运气好一些
因为模式串中最靠后的A
还不至于过于靠后
我们可以放心地移动模式串 从而使得这个A与这个A彼此对齐
的确 经过适当的右移之后
模式串中的这个A的确可以与文本串中的这个A彼此对齐而且匹配
而在接下来的一轮扫描比对中
我们会高兴地发现
所有字符都是匹配的
于是 算法至此即告结束
反观算法刚才的这一次执行过程
我们对它的性能的确很难满意
因为我们注意到在前后的3次右移中
居然有两次只移动了一步
而进一步的观测之后我们或许会发现
如果能够借助一些其他的策略
我们本来应该可以移动得更快
就以刚才的第一轮比对为例
当我们失败于主串的C时
我们不仅可以获得坏字符之类的负面信息
同时还可以获得更多的正面信息
你能看出来吗
没错 就是在这次失败的比对之前
我们刚刚做过的4次成功比对
通过这些信息 我们能够获得什么帮助和启示呢
作为事后诸葛亮 我们可以发现
根据刚才的这些正面信息
我们完全可以断定接下来的两次对齐都是不必要的
原因在于 按照这两个对齐位置
在刚才这4个成功比对的位置处 都是失配的
自然地 这也就注定了这两次对齐位置都必然是徒劳无功的
而在进一步的观察之后
或许你应该能够发现一个更好的消息
是的
如果将此类成功的信息依然称作经验
那么我就可以与KMP算法一样
对它们加以利用
而且相应的准备工作也可以通过预处理的方式提前完成
比如 就针对这样一段区间
我们应该能够以某种方式
事先从模式串中将与之匹配的部分提取出来
从而使得我们在确定下一对齐位置的时候
可以保证此前的这次对齐
能够继续得以延续
果真如此 我们就可以在第一轮比对失败之后
直接将模式串一步移送到位
从而有望进一步地提高BM算法的效率
仿照坏字符的命名方式
我们也不妨将这种匹配的后缀称作好后缀
-选课之前
--写在选课之前
--宣传片
-考核方式
--考核方式
-OJ系统说明
--关于OJ
--1-注册与登录
--2-界面与选课
--3-提交测试
-关于课程教材与讲义
--课程教材与讲义
-关于讨论区
--关于讨论区
-微信平台
--html
-PA晋级申请
--PA晋级
-(a)概述
--07A-1 纵览
--07A-5 接口
-(a)概述--作业
-(b1)BST:查找
-第七章 二叉搜索树--(b1)BST:查找
-(b2)BST:插入
-(b2)BST:插入--作业
-(b3)BST:删除
-第七章 二叉搜索树--(b3)BST:删除
-(c)平衡与等价
-(c)平衡与等价--作业
-(d1)AVL树:重平衡
-第七章 二叉搜索树--(d1)AVL树:重平衡
-(d2)AVL树:插入
-(d2)AVL树:插入--作业
-(d3)AVL树:删除
-(d3)AVL树:删除--作业
-(d4)AVL树:(3+4)-重构
-(d4)AVL树:(3+4)-重构--作业
-本章测验
--章节测验
-(a1)伸展树:逐层伸展
--习题
-(a2)伸展树:双层伸展
--习题
-(a3)伸展树:算法实现
--习题
-(b1)B-树:动机
--习题
-(b2)B-树:结构
--习题
-(b3)B-树:查找
--习题
-(b4)B-树: 插入
--习题
-(b5)B-树: 删除
--习题
-(xa1)红黑树:动机
--习题
-(xa2)红黑树:结构
--习题
-(xa3)红黑树:插入
--习题
-(xa4)红黑树:删除
-本章测验
--习题
-(b)散列:原理
--09B-3 数组
--09B-4 原理
--09B-5 散列
--09B-6 冲突
--习题
-(c)散列:散列函数
--习题
-(d1)散列:排解冲突(1)
--习题
-(d2)散列:排解冲突(2)
--习题
-(e)桶/计数排序
--习题
-本章测验
--本章测试
-(a1)需求与动机
--习题
-(a2)基本实现
--习题
-(b1)完全二叉堆:结构
--习题
-(b2)完全二叉堆:插入与上滤
--习题
-(b3)完全二叉堆:删除与下滤
--习题
-(b4)完全二叉堆:批量建堆
--习题
-(c)堆排序
--习题
-(xa1)左式堆:结构
--习题
-(xa2)左式堆:合并
--习题
-(xa3)左式堆:插入与删除
-本章测验
--本章测试
-(a)ADT
--习题
-(b1)串匹配
--习题
-(b2)蛮力匹配
--习题
-(c1)KMP算法:从记忆力到预知力
--习题
-(c2)KMP算法:查询表
--习题
-(c3)KMP算法:理解next[]表
--习题
-(c4)KMP算法:构造next[]表
--习题
-(c5)KMP算法:分摊分析
--习题
-(c6)KMP算法:再改进
-(d1)BM_BC算法:以终为始
-(d2)BM_BC算法:坏字符
-(d3)BM_BC算法:构造bc[]
-(d4)BM_BC算法:性能分析
-(e1)BM_GS算法:好后缀
-(e2)BM_GS算法:构造gs表
-(e3)BM_GS算法:综合性能
-(f1)Karp-Rabin算法:串即是数
-(f2)Karp-Rabin算法:散列
-本章测验
--本章测试
-(a1)快速排序:算法A
-- 12a1-5: 实例
--习题
-(a2)快速排序:性能分析
--习题
-(a4)快速排序:变种
-(b1)选取:众数
-(b3)选取:通用算法
--习题
-(c1) 希尔排序:Shell序列
--习题
-(c2)希尔排序:逆序对
-本章测验
--本章测试