用途
KMP算法:它是用来匹配字符串的,对于文字的检索和查找有很大的用处。说白了,它就是用来查看一个字符串中是否包含有另外一个字符串,如果有,则返回第一个字符的位置,否则返回-1,表示没有找到。
简单介绍
1. 当然,除了KMP匹配算法,还有普通的字符串匹配算法,但是它的效率太低了,而KMP算法则是进一步对普通方法的改进,可以显著提高字符串的匹配效率。首先先来介绍一下普通的字符串匹配方法,通过比较来发现普通算法和KMP算法的不同。
普通匹配方法的基本思想是:让模式串的第一个字符与主串的第一个字符比较,如果相等,则继续比较后面的字符。如果和主串的第一个字符就不相同,则继续用模式串的第一个字符和主串的第二个字符比较。这样看起来似乎很合理,但是,如果模式串的前几个字符都匹配成功,在后续字符的比较中有不同的,则下一次的比较,模式串仍然要回到第一个字符,再去和主串比较。
下面用一个例子来说明一下:
可见,这时比较到第三个字符的时候,出现了不同。
而下一次的比较中,模式串依然从第一个字符开始和主串的第二个字符比较。
如果主串的长度为n,模式串的长度为m,则普通算法的最坏时间复杂度为O(n*m)。
2. 而KMP算法则使得模式串不用每次都回到第一个字符,它会利用之前已经比较过的字符,从而确定下次比较从第几个字符开始。
KMP算法的核心就是确定每次匹配不成功时,下次比较开始的位置。
那么怎么确定这个位置呢?它是和匹配不成功时,所在字符的位置有关的。这个位置就是所在字符之前的所有字符的 前缀和后缀 的最大相同长度。拿上面的例子来说,下次的开始的比较位置和模式串中下标0~2的字符有关。
什么是前缀和后缀的最大相同长度呢?在这之前,要先明白前缀是什么?前缀就是一个字符串的前n个字符(0 < n < 字符串的长度),即不包括它自身。比如:abababb的前缀有:a、ab、aba、abab、ababa、ababab。后缀的意思和前缀相反。前缀和后缀的最大相同长度就是,先找出所有相同的前缀和后缀,然后取其中长度最长的那一组。
比如:拿ababa来举例,ababa中前缀有:a、ab、aba、abab;后缀有:a、ba、aba、baba。那么前缀和后缀相同的有:a和aba,但是最大相同长度是aba。
明白了什么是前缀和后缀的最大相同长度后,我们用next数组来记录这个位置。即先求出模式串中所有子串的前缀和后缀最大相同长度。
next数组 | 模式串中与数组(下标)对应的下标之前的字符 | 前缀和后缀的最大相同长度 |
---|---|---|
next[0] | null | -1 |
next[1] | a | 0 |
next[2] | ab | 0 |
next[3] | aba | 1 |
next[4] | abab | 2 |
next[5] | ababa | 3 |
next[6] | ababab | 4 |
还拿普通算法的例子来看一下,KMP算法是如何匹配的:
可以发现,KMP算法的下次比较位置不是0,而是1,而1也正是next[3]中所存的数。
小结
利用改进的KMP算法可以显著提高字符串的匹配效率。这篇博客只是我对于KMP算法的一个初步理解,只是简单的介绍了KMP算法的基本思想,如果哪里有不正确的地方,还请各位大神指出。对于代码我还会继续学习的,KMP算法就简单介绍到这儿,感谢您的阅读。