字符串匹配是一个很常见的问题,可以扩展为模式的识别,解决字符串问题的思想被广泛地应用。介绍四种解决该问题的办法,包括:最朴素的遍历法,Rabin-Karp算法,自动机机匹配,Knuth-Morris-Pratt算法即耳熟能详的KMP。
在一开始,先对时间复杂度做出一个总扩(从大到小):【1】朴素法:O( (n-m+1)m );【2】Rabin-Karp:预处理:O(m),匹配:最坏O( (n-m+1)m ),但是平均和实际中比这个好得多;【3】自动机:预处理O(m|Σ|),匹配O(n);【4】KMP:预处理O(m),匹配O(n)。 其中, m代表模式P的长度,n代表被匹配的数组S的长度,Σ代表P和S的字符表。
接下来分开说一下他们是怎么工作的,和他们的思想。
- 朴素法
朴素法的效率低的问题在于,它几乎忽视了所有的信息,每一次匹配都是“全新地”。如果P=abc,S=abdabc,从位置0开始,当我们匹配到 位置2,即c != d,朴素的做法是下一步从位置1开始匹配, 然而,在之前的匹配过程中,我们可以知道位置1的值b必然不匹配位置0的a。这是我们光通过P就能知道的,因为既然前一步已经开始去匹配位置2了,证明说明0和1已经成功匹配,而通过P自己,我们知道P的位置1不匹配0,则前一步的S位置1必然也不匹配P的位置1,这样就可以跳过这一步。
问题在于,告诉程序跳过多少步,这就是我们接下来的算法要做的。显然,跳过得越多匹配越快,同时我们为了尽可能得到跳步的信息,可能需要进行预处理,预处理会产生另外的时间。
</