关于KMP算法我只想说:"太难了",学了一天下来还是模模糊糊.但是还是明白了具体思路和next数组,nextval数组的求法
什么是KMP算法
KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,简称KMP算法。KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是通过一个next()函数实现,函数本身包含了模式串的局部匹配信息
next数组
在KMP中求出next数组是关键,所以我将分享一下next数组的求法
- 首先我们需要知道什么是前缀,后缀
-
前缀:一个字符串的前缀是从开头开始的连续子串。例如,在字符串 "abcd" 中,"a"、"ab" 和 "abc" 都是它的前缀。
-
后缀:一个字符串的后缀是从结尾开始的连续子串。例如,在字符串 "abcd" 中,"d"、"cd" 和 "bcd" 都是它的后缀。
2.要知道next[1]=0,next[2]=1是固定的 .要求的next[j]=最长相同前缀后缀+1.比如ababc 要求这个的next数组 首先 1.a: next[1]=0 2.b:next[2]=1 固定的 3.a:这里它前面的子串为ab ,ab的最长相同前缀后缀为0 所以+1 则next[3]=1 4.b:这里它前面的子串为aba ,aba的最长相同前缀后缀为1所以 next[4]=1+1=2 5.c:这里它前面的子串为abab ,abab的最长相同前缀后缀为2所以 next[4]=2+1=3
3.next数组对应的值也就是让对应的第几个字母达到当前的匹配位置进行匹配
如有不懂推荐去b站上看up主kadadaa的详细讲解
下面是实现代码(目前我自己也还是是懂非的) 建议看看小甲鱼的讲解
include <stdio.h>
#include <string.h>
#define maxsize 100
void Nextval(char T[], int* next)
{
int lenT = strlen(T);
int k = -1;//前缀
int j = 0;//后缀
next[0] = -1;
while (j < lenT)
{
if (k == -1 || T[j] == T[k])
{
j++;
k++;
if (T[j] != T[k])
{
next[j] = k;//之前只有这一行
}
else
{
next[j] = next[k];/*为不能出现T[j] = T[ next[j ]],
所以当出现时连续进行两次回溯,k = next[next[k]] */
}
}
else
{
k = next[k]; //回溯
}
}
}
int KMP(char S[], char T[])
{
int i = 0, j = 0, lenS, lenT;
lenS = strlen(S);
lenT = strlen(T);
int next[maxsize];
Nextval(T, next);
while (i < lenS && j < lenT)
{
if (j == -1 || S[i] == T[j])
{
i++;
j++;
}
else
{
j = next[j];
}
}
if (j == lenT)
{
printf("Match succeed!\n");
return i - j;
}
else
{
printf("Match failed!\n");
return -1;
}
}
int main()
{
char S[maxsize], T[maxsize];
int target;
strcpy_s(S, "AAAAAAAAAAttract");
strcpy_s(T, "Attract");
target = KMP(S, T);
printf("Position is %d\n", target);
return 0;
}