提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
KMP字符串的模式匹配算法
前言
提示:以下是本篇文章正文内容,下面案例可供参考
一、KMP模式匹配算法
KMP模式匹配算法,是由三位科学家前辈(克努特-莫里斯-普拉特)发表,可以极大地避免重复遍历的情况,从而降低算法的时间复杂度
如果字符串非常长,不是依次性地调入内存,此情况更加适合KMP,为啥?因为KMP避免了不必要的回溯,而BF是需要回溯的,即回去找之前已经匹配过的字符。
二、C语言实现
#include<stdio.h>
void get_next(char* T, int *next){
// 1 < i<= T[0]
//求模式串T的next值,并放入next数组
int i = 1;int j = 0;next[1] = 0;
while (i <= T[0]){/*如果指针i在串的长度范围内,循环继续*/
if (j==0 || T[i] == T[j]){/*T[i]为后缀的第i字符,T[j]为前缀的第j个字符
如果相等,则i下一位的next值next[i+1]=j+1*/
i++;
j++;
next[i] = j;
}
else j = next[j]; /*不相等,则j回溯*/
}
}//get_next
int index_kmp(char *S, char *T, int pos){
// 1<=pos<=S的长度
int i = pos; /*pos是主串当前位置的下标值*/
int j = 1; /*j是模式串当前位置的下标值*/
int next[255]; /*定义一个next数组*/
get_next(T, next);/*得到模式串T的next数组*/
while (i<=S[0] && j<=T[0]){ /*如果指针i小于主串S的长度且j小于模式串T的长度,
即指针都在各自的范围内,则循环继续*/
if (j==0 || S[i] == T[j]){/*若i所指的字符和j所指的字符相等,则继续比较后面的字符;
如果模式串的指针j回溯到0了,也继续比较下一位!*/
++i;
++j;
}else
j = next[j]; /*如果字符不相等,则j回溯;注意这里相比于BF算法,只是j回溯了,
而i是没有回溯的,这样就避免了不必要的比较*/
}
if (j>T[0]){
return i - T[0];
}
else return 0;
}
//验证一下!
int main(int argc, char const *argv[]){
char T[] = " ababcababa";
T[0] = 10;//首位存字符串T的长度
char S[] = " swap123ababcababassxyz";
S[0] = 23;//同样首位存字符串S的长度
printf("T串在S串的%d处匹配成功!\n", index_kmp(S, T, 2));
return 0;
}
结果:
三、总结
时间复杂度:
KMP:O(m+n)
BF:O((n-m+1)*m)最坏情况
例如:
S:0000 0000 0000 0001 m=16
T:0001 n=4
KMP: m+n=20 次!
BF:(16-4+1)*4=52 次
Obviously,KMP is better than BF!