1.KMP的工作原理
在匹配主串之前,先计算出模式串每个字符的最长公共前后缀保存在next数组中。然后使用两个变量分别指向模式串与主串,依次进行比较,如果遇到不相等的情况,模式串前移到最长公共前后缀+1的位置继续与主串进行比较。
2.KMP的算法思想
通过记录下模式串每个字符的最长公共前后缀,在匹配失败后不必回溯至开始位置,而是回溯到最长公共前后缀位置继续比较,节省时间。
我们把模式串的每个字符的最长公共前后缀保存在一个next的数组中,这样我们在遇到任何一种不匹配的情况下都可以对照next数组中的值直接回溯到最长公共前后缀位置。
3.KMP的代码实现
void KMP(char *pattern, char *text) {
int M = strlen(pattern);
int N = strlen(text);
int i = 0;
int j = 0;
while (i < N) {
if (pattern[j] == text[i]) {
j++;
i++;
}
if (j == M) {
j = Next[j - 1];
} else if (i < N && pattern[j] != text[i]) {
if (j != 0) {
j = Next[j - 1];
} else {
i++;
}
}
}
}
4.next函数
Next函数的思想:
通过计算模式串的最长公共前后缀,当匹配失败时,记录回退的位置
实例1:
模式串:ABBAABB
因为第1个字符没有前缀,直接在next中标记为0;然后第2个字符没有公共前后缀,所以记为0+1=1;第3个字符也没有公共前后缀,记为1;第4个字符也记为1;第5个字符的最长公共前后缀为1,所以记为1+1=2;第6个记为2,;第7个记为3。
实例2:
模式串:BBABBAA
同上面一样,next数组应该为:012123。首先定义变量i=1,j=0;然后依次判断每个字符的前缀:如果pattern[i]==pattern[j]那么next[++i]=++j;否则j回退到它指向的字符的最长公共前后缀处,即j=next[j];
5.next函数的代码实现
int GetNext(char pattern[],int length,int next[]){
next[1]=0;
int i=1;j=0;
while(i<=length){
if(j==0||pattern[i]==pattern[j]){
next[++i]=++j;
}else{
j=next[j];
}
}
}