KMP 算法
KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,因此人们称它为克努特—莫里斯—普拉特操作(简称KMP算法)。KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是通过一个next()函数实现,函数本身包含了模式串的局部匹配信息。KMP算法的时间复杂度O(m+n)。
串:一些列有限字符的集合
串: 操作是以串为单元的
1.固定长度的串
#define MAXSIZE 10
struct String
{
char str[MAXSIZE];//存储串字符的数组
int len;//当前串的长度
};
2.变长的串
struct String
{
char* pstr;//开辟内存
int totalsize;//串当前最大的长度
int cursize;//串当前的有效长度
};
串可以做一下操作:
1.赋值
2.比较
3.合并
设主串(T)为:a b a c a a b a c a b a c a b a a b b
模式串(W)为:a b a c a b
在KMP算法中,对于每一个模式串我们会事先计算出模式串的内部匹配信息,在匹配失败时最大的移动模式串,以减少匹配次数。比如,在简单的一次匹配失败后,我们会想将模式串尽量的右移和主串进行匹配。右移的距离在KMP算法中是如此计算的:在已经匹配的模式串子串中,找出最长的相同的前缀和后缀,然后移动使它们重叠。
在第一次匹配过程中
T: a b a c a a b a c a b a c a b a a b b
W: a b a c a b
给的P字符串是“abcdaabcab”,经过KMP算法:
(1) next[0]= -1 意义:任何串的第一个字符的模式值规定为-1。
(2) next[j]= -1 意义:模式串T中下标为j的字符,如果与首字符相同,且j的前面的1—k个字符与开头的1—k个字符不等(或者相等但T[k]==T[j])(1≤k<j),如:T=”abCabCad” 则 next[6]=-1,因T[3]=T[6].
(3) next[j]=k 意义:模式串T中下标为j的字符,如果j的前面k个字符与开头的k个字符相等,且T[j] != T[k] (1≤k<j)即T[0]T[1]T[2]…T[k-1]==T[j-k]T[j-k+1]T[j-k+2]…T[j-1]且T[j] != T[k].(1≤k<j);
(4) next[j]=0 意义:除(1)(2)(3)的其他情况。
核心代码:
int KMP(char* s, char* t)
{
int slen = strlen(s);//主串的长度
int tlen = strlen(t);//模式串的长度
int i = 0;//i 主串的下标
int j = 0;//j 模式串的下标
int next[7] = { -1, 0, 0, 0, 1, 2, 3 };
//int* next = (int*)malloc(sizeof(int)*tlen);
while (i < slen && j < tlen)//主串没有匹配完成 字串没有匹配完成
{
if (j == -1 || s[i] == t[j])
{
i++;
j++;
}
else
{
j = next[j];
}
}
if (j == tlen)
{
return i - tlen;
}
return -1;
}
int main()
{
char *s = "ABCABCABCCABCABCD";
char *t = "ABCABCD";//10
int index = KMP(s, t);//10
printf("%d\n", index);
return 0;
}
2020-33-30-21.45创作