当前课程知识点:数据结构(下) > 第十一章 串(下) > (d1)BM_BC算法:以终为始 > 11d1-2: 善待教训
让我们将视线拉回到蛮力算法
你应该记得 蛮力算法一次典型的运行过程
可以表示为这样一幅图
是的 如果将文本串固定在这里
那么 这些就是模式串在不同对齐位置处的历史快照
事实上 模式串在每一个对齐位置的故事 都是类似的
首先 要经过若干次成功的比对
在这里 用绿色的线条来表示
而接下来 总是一次失败的比对
此后 在下一位置的故事依然
该算法也需要经过若干次成功的比对
然后终止于失败的比对
而在接下来的第三次、第四次、第五次等等等等
各次对齐中 也同样都是要经过若干次成功的比对
并终止于一次失败的比对
因此 就局部的每一次对齐而言
我们都需要经过若干次的成功
并终止于一次失败
请注意 在每次对齐中尽管只有一次失败
但却足以确定相应的对齐位置是无效的
事实上 只有最后一次对齐位置才有可能是成功的
因此 就整体而言恰好与刚才局部的模式相反
多次失败 以及至多一次的成功
因此 如果我们着眼于改进蛮力算法
那么 我们的目标与其说是要加速匹配
不如说是要加速失败
或更准确地讲
要尽可能快速地、低成本地排除掉无效的对齐位置
事实上 KMP等算法就是这样
你应该记得
KMP会聪明地排除掉其中的若干个 甚至是大量的对齐位置
从而大大地节省计算的成本
甚至从某种意义上讲
我们或许能够做得比KMP还要出色
正如我们刚才所指出的
就排除某个对齐位置而言
相应的那些成功的比对
并不重要
而在这个意义上起实质作用的 反而是那些失败的比对
如果真的像刚才说的那样
我们总是需要在排除多个无效的对齐位置之后
才能够确定最终有效的对齐位置
那么 我们反倒应该更加期盼这种失败的比对出现得更早
比如 按照这种思路的一种极端情况就是
我们或许可能只做这些失败的比对
就足以排除掉相应的对齐位置
无论是它
还是它
以及它
它
诸如此类
正如我们在习题解析中所指出的那样
为了排除掉一个对齐位置
我们平均只需做常数次比对
而且在理想平均的情况下
你甚至不必去关心
哪个字符更有可能首先失败
而只需按部就班地从前向后、自左而右地依次比对就可以了
是的 如果我们的关注力只停留于单个的比对位置
那么固然如此
但是 倘若我们将所有的对齐位置作为一个整体来考虑
我们就会发现 实际上 在每一个对齐位置处
按照什么样的次序去尝试对比各字符
却十分敏感而关键
我们的建议是 你或许应该优先去比对那些靠后、乃至最靠后的字符
也就是说
与我们常规的做法恰恰相反
或许你应该更多地去关注教训
是的 如果教训的确不能避免的话
或许我们应该让它更早地暴露出来
或者再准确地讲
应该让更大的教训 更早地暴露出来
那么 为什么就串匹配算法而言
在越靠后的位置所获得的教训
所具有的价值越高呢
-选课之前
--写在选课之前
--宣传片
-考核方式
--考核方式
-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)希尔排序:逆序对
-本章测验
--本章测试