一、KMP算法介绍:
对于两个字符串,如果我们需要在一个串中找到另一个串的出现数量,有两种方法:
在待匹配串中设置指针i,每匹配完一次模式串则往后移一位,该算法的时间复杂度是O(n*m),空间复杂度O(n+m)。
对于这种方法,我们注意到,很多需要匹配的操作实际上是不必要的,比如模式串abcde,待匹配串abcdeabcde,当匹配完b之后移动到匹配c,是完全没有必要的。
因此,为了避免这种情况,KMP算法应运而生。KMP算法对于一个字符串匹配的时间复杂度是O(n+m),空间复杂度是O(n+m)。
以下是KMP算法的实现过程:
KMP算法是通过对模式串预处理,找出失配之后模式串的匹配指针移动的位置,来减少无意义的匹配。这个预处理产生的数组被称为next数组,也称fail数组(理解fail数组的机制就可以对AC自动机的fail指针有更为深刻的理解),以下统一称为fail数组。
fail[i]的意义:
设字符串的字符序号从1开始计数,i是字符串的前i个字符的前缀和后缀的最长相同字符(前后缀均不包括它本身)。
fail数组的求法:
fail数组通过fail[i-1]的信息求解fail[i],利用模式串自己和自己匹配,求得fail数组。fail[0]表示空字符串的前缀和后缀的相同字符长度,显然没有意义,设为-1。设置指针j和k,j=-1,k=0。j为匹配字符位置指针,k为待匹配字符位置指针。然后,如果fail[i-1]=-1,就意味着k的位置为字符串的第一个字符位置,此时得到fail[i]=0;如果fail[i-1]>-1,即表明k的位置大于字符串的第一个字符位置,此时分两种情况:
一、如果两个指针对应的字符相等,则都可以向右移动一位,同时fail[i]=fail[i-1]+1;(若一直都匹配成功,fail[i-1]=j,然后++j)
二、如果两个指针对应的字符不相等,则j就要回溯,回溯到哪里呢,这时就要使用fail已经求出的信息了。假设在这之前均匹配成功,由fail数组的定义,字符串中0~fail[i]-1和i-fail[