文章目录
今日格言: 困难就像弹簧,你弱它就强。
考纲内容及重难点
考纲内容只有字符串模式匹配,重点考的是KMP算法(next数组)以及KMP算法的修正(改进)目前真题所有考察方式均为选择题。
出题方式常见这几种:
KMP
算法的特点和过程- 求某一个给定串的
next
数组/nextval
数组 - 模式匹配过程中进行的单个字符间的比较次数
- 匹配过程中i,j的值
- 子串S滑动的距离
不是简单题,一不小心就很容易错,一定要注意。
对于底子薄弱的本人来说,以下均为重难点: - 模式匹配的暴力匹配算法
KMP
匹配算法的原理及next
数组的推理过程KMP
算法的进一步优化,了解nextval
数组的求解方法
知识框架回忆图
基本概念
为什么要学串?学对串的一些基本操作?学习串的模式匹配?
字符串简称串,计算机上非数值处理的对象基本都是字符串数据。我们常见的信息检索系统(如搜索引擎,谷歌)、文本编辑程序(如Word)、问答系统、自然语言翻译系统等,都是以字符串数据作为处理对象的。
串(string)是由零个或多个字符组成的有限序列。一般记为
S
=
′
a
1
a
2
…
a
n
′
(
n
≥
0
)
S='a_1a_2…a_n'(n≥0)
S=′a1a2…an′(n≥0)
其中,S是串名,单引号(双引号,不同的编程语言引用方式不同)括起来的字符序列是串的值,a_i可以是字母、数字或其他字符;串中字符的个数n称为串的长度。n=0时的串称为空串(用
∅
\varnothing
∅表示)。
串中任意多个连续的字符组成的子序列称为该串的子串
,包含子串的串称为主串
。子串在主串中的位置以子串的第一个字符在主串中的位置来表示(往往从1开始)。当两个串的长度相等且每个对应位置的字符都相等时,称这两个串是相等
的。
以字符串"abcdefg"为例,空串,“a”,“abcdefg”都是该字符串的子串,但是"ace"不是该字符串的子串,因为虽然a、c和e都在主串出现,但不连续。
串的模式匹配
假设两个字符串的长度分别为n和m,且满足n>=m,则判断其是否相等的算法时间复杂度是O(n) ×
注意啊,这不是求串的模式匹配,而是判断两个串是否相等,因为n>=m,所以至多比较m次后,就能得到是否相等的结论,因此时间复杂度和n无关,是O(m)。
暴力匹配算法(Brute Force)
KMP算法
字符串的前缀、后缀和部分匹配值PM
前缀
指除最后一个字符以外,字符串的所有头部子串。
后缀
指除了第一个字符以外,字符串的所有尾部子串。
部分匹配值
指字符串的前缀和后缀的最长相等前后缀长度。下面以’ababa’为例进行说明:
- 'a’的前缀和后缀都为空集,最长相等前后缀长度为0,也就是说无子集。
- 'ab’的前缀为{a},后缀为{b},最长相等前后缀长度为0,也就是说无子集。
- 'aba’的前缀为{a,ab},后缀为{a,ba},最长相等前后缀长度为1,就是它们的子集a的长度。
- 'abab’的前缀为{a,ab,aba},后缀为{b,ab,bab},最长相等前后缀长度为2,就是它们的子集ab的长度。
+** 'ababa’的前缀为{a,ab,aba,abab},后缀为{a,ba,aba,baba},最长相等前后缀长度为3,就是它们的子集aba的长度**。
回到我们上述举的那个例子:主串S为"ababcabcacbab",模式串为"abcac"。
根据上述讲的串的部分匹配值PM的定义,我们可以得到模式串"abcac"的部分匹配值为00010,
具体过程如下:
将部分匹配值写成数组形式,就得到了部分匹配值的表。
KMP算法的特点是在模式匹配时,主串不回溯,指示主串的指针不会变小。
编号 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|
S | a | b | c | a | c |
next | -1 | 0 | 0 | 0 | 1 |
next数组
在KMP
匹配中,用next
数组存放模式串的部分匹配信息,当模式串位j
与主串位i
比较时,两个字符不相等,则j的位移方式是
j
=
n
e
x
t
[
j
]
j=next[j]
j=next[j]。
KMP算法的进一步优化(nextval数组)
错题
本题选B。
归纳总结与思维拓展
归纳总结
KMP算法对于初学者来说可能不太容易理解,读者可以尝试多读几遍本章的内容,并参考一些其他教材相关内容来巩固这个知识点。
学习KMP算法时,应从分析暴力法的弊端入手,思考如何去优化它。实际上,已匹配相等的序列就是模式串的某个前缀,因此每次回溯就相当于模式串与模式串的某个前缀比较,这种频繁的重复比较是效率低的原因。这时,可从分析模式串本身的结构入手,以便得知当匹配到某个字符不等时,应该向后滑动到什么位置,即已匹配相等的前缀和模式串若首尾重合,则对齐它们,对齐部分显然无须再比较,下一步则是直接从主串的当前位置继续进行比较。
思维拓展
编程实现:模式串在主串中有多少个完全匹配的子串?(注意,统考不会考KMP算法题)