当前课程知识点:数据结构(下) > 第十一章 串(上) > (c3)KMP算法:理解next[]表 > 11C3-3: 通配哨兵
至此 严谨的你或许会有一个疑问
这里的候选者集合N(P,j)
一定是非空的吗
因为对于一个空集而言
无论是选取最大元还是选取任何一个元素 都是无从谈起的
然而实际上 这种担心是不必要的
在这里我们注意到
只要j是正数
那么这个集合就必然包含0
然而遗憾的是j有可能恰好就是0
当然 此时P[j]所对应的前缀P[0,j)也自然是空串
而我们知道 对于空串而言
所谓的真前缀和真后缀都是不可能存在的
也就是说 此时的候选集合 的确是一个空集
为了修补这一漏洞
KMP算法所给出的建议是
统一将next表中的第0项置为-1
那么 如何来理解这个-1呢
一种形象而有效的理解方式就是
为每一个模式串在首字符的前端 也就是等效于秩为-1的位置
增设一个哨兵
当然 与所有假想的哨兵一样
这个哨兵并不需要真实地存在
但是在逻辑上
这个哨兵却等效于一个与所有字符都通配的字符
你应该还记得我们在介绍KMP主算法时所搁置起来的一个问题
也就是其中那个if语句所对应的条件式
你应该记得 除了常规的字符比对逻辑
KMP还增设了另一个并列的逻辑
也就是j是否小于0
现在 你应该恍然大悟了吧
是的 在正常的情况下
所谓的j<0无非就是一种情况
也就是说 在刚刚过去的那一轮比对中 我们失败于首字符P[0]
于是 按照我们刚才所建议的那种理解方式
KMP将用这个假想的通配符 去与文本串中失配的那个T[i]继续比对
既然是通配符
所以接下来的第一次比对必然会成功
也正因为此 我们可以将j<0的条件 在语义上与字符的成功比对等效起来
也就是说 这个合成的逻辑判断式
在语义上完全等效于一次成功的比对
由此可见 巧妙地引入和设置哨兵
在程序和算法设计过程中
是一种非常高明的处理手法
KMP就是这方面的一个典型范例
概括而言 这种手法的高明之处主要体现在两个方面
首先 在代码实现上 可以使得算法的描述更为简洁
其次 通过相应地建立一种假想的模型
反过来 也可以使得我们对算法的理解更为统一和深入
我们知道 包括伽利略在内的许多著名物理学家
都擅长于在头脑中进行所谓的虚拟实验
而实际上 计算机科学中的这种假象模式
与物理学中的虚拟实验
有着异曲同工之妙
至此 我们已经对KMP所使用的那个next查询表
有了足够深刻的认识
那么接下来一个问题自然就是
从计算的角度来看
这样一份查询表又当如何构造出来呢
为此 我们又需要花费多少成本呢
-选课之前
--写在选课之前
--宣传片
-考核方式
--考核方式
-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)希尔排序:逆序对
-本章测验
--本章测试