简单模式匹配算法
想象一下,你手里有一本厚厚的书(主串),你想在这本书里找到某个特定的词(模式串)。简单模式匹配算法就像是你一页一页地翻,每次只看这一页里和你想要找的词一样长的那部分,然后和这个词比较。如果发现不一样,你就翻到下一页继续找。这种方法的缺点是,有时候你可能已经看了一半,但发现不一样,还得翻回去重新开始,这就比较浪费时间。
KMP算法
KMP算法就像是你有一个更聪明的助手。在你翻书的时候,如果发现当前这一页的某个部分和你想要找的词有相似之处,即使后面不一样,你的助手也会告诉你,根据已经匹配的部分,可以跳过一些不需要再看的地方,直接从新的位置开始比较。这样,你就不需要每次都从头开始找了,效率自然就提高了。
KMP算法的基本概念
前缀:就像你要找的词的前半部分。
后缀:就像你要找的词的后半部分。
部分匹配值:就是前缀和后缀中最长的相同部分。
KMP算法的步骤
先计算出你要找的词的每个部分匹配值。
当你在书里找这个词的时候,如果发现当前看的部分和词不完全一样,就根据部分匹配值告诉你可以跳到哪个位置继续比较。
举个例子
比如你要在书里找“ababa”,你可以先算出这个词的每个部分匹配值,然后根据这个值来决定每次跳过多少。
优点
KMP算法的好处是,你不需要每次都从头开始找,这样找起来就快多了。
进一步优化
有时候,KMP算法的助手(next数组)可能也不是那么完美,但可以通过一些方法来让它更聪明,这样找东西的时候就更快了。
知识点链接
简单的模式匹配算法
概念:模式匹配是查找子串(模式串)在主串中的位置的过程。
算法思想:通过比较主串中与模式串长度相同的子串,逐个与模式串进行比较。如果当前子串与模式串的某个字符不匹配,就放弃当前子串,继续检索下一个子串。
缺点:当子串与模式串不匹配时,主串的指针会回溯,导致时间开销增加。最坏情况下的时间复杂度为O(mn),其中n和m分别为主串和模式串的长度。
改进的模式匹配算法 - KMP算法
基本概念:
前缀:除最后一个字符外,字符串的所有头部子串。
后缀:除第一个字符外,字符串的所有尾部子串。
部分匹配值:字符串的前缀和后缀的最长相等前后缀长度。
算法思想:在暴力匹配中,当匹配失败时,模式串后移一位再从头比较。如果已匹配的前缀序列中存在某个后缀,该后缀正好是模式的前缀,则可以将模式串向后滑动到与这些相等字符对齐的位置,并继续比较。
右移位数:可以通过公式Move = (j-1) - PM[j-1]计算,其中PM[j-1]是部分匹配值。进一步改写为Move = (j-1) - next[j],这里的next[j]表示在子串第j个字符与主串发生失配时,模式串应跳到哪个位置与主串当前位置进行比较。
示例:以字符串'ababa'为例,计算其部分匹配值。通过计算每个子串的前缀和后缀的最长公共长度,得到的部分匹配值为0, 0, 0, 1, 2, 3。
时间复杂度:O(m+n),其中m是模式串长度,n是主串长度。
优点:主串不会进行回溯,提高了效率。
KMP算法的进一步优化
KMP算法的next数组在某些情况下可能存在缺陷,可以通过构造nextval函数进行进一步优化,以提高算法的效率和准确性。