作者: sleepygod
日期: 10-20
也许 不负光阴就是最好的努力 而努力就是最好的自己

KMP算法简单实现
1.算法思想
KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,因此人们称它为克努特—莫里斯—普拉特操作(简称KMP算法)。KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是通过一个next()函数实现,函数本身包含了模式串的局部匹配信息。KMP算法的时间复杂度O(m+n)

区别:KMP 和 BF 唯一不一样的地方在,我主串的 i 并不会回退,并且 j 也不会移动到 0 号位置
具体实现如下:
首先我们求出next数组,因为next数组记录每一次回溯的位置

为了方便计算,我将next数组每一个值与上述相比都减一.
next[0]=-1,next[1]=0,接下来,就判断p[i-1]是否与p[next[i-1]]是否相等,如相等则next[i]=next[i-1]+1;如不相等,则继续回溯,直至-1位置.
next数组优化 如果p[i]=p[next[i]],则,nextval[i]=nextval[next[i]],否则nextval[i]=next[i].
2.算法实现
int* getnext(const char* p)
{
int* next = (int*)malloc(strlen(p) * sizeof(int));
*(next+0) = -1;
*(next + 1) = 0;
for (int i = 2; i < strlen(p); i++)
{
int tmp = next[i - 1];
while (tmp>-1)
{
if (p[i - 1] == p[tmp])
{
break;
}
else
{
tmp = next[tmp];
}
}
next[i] = tmp + 1;
}
return next;
}
int *getnextval(const char *p,const int *next)
{
int* nextval = (int*)malloc(strlen(p) * sizeof(int));
*nextval = -1;
for (int i = 1; i < strlen(p); i++)
{
if (p[i] == p[next[i]])
{
nextval[i] = nextval[next[i]];
}
else
{
nextval[i] = next[i];
}
}
return nextval;
}
void KMP(const char* p1,const char* p2)
{
int* next = nullptr;
next = getnext(p2);
int* nextval = nullptr;
nextval = getnextval(p2, next);
int answer = -1;
int i = 0, j = 0;
while (i < strlen(p1) && j < strlen(p2))
{
if (p1[i] == p2[j])
{
j++;
i++;
}
else
{
j = nextval[j];
if (j == -1)
{
i++;
j++;
}
}
}
if (j == strlen(p2))
{
answer = i - strlen(p2)+1;
}
cout << "第" << answer<<"个字符,开始";
cout << endl;
for (int i = 0; i < strlen(p2); i++)
{
cout << p1[answer - 1 + i];
}
}
运行结果:

本文探讨了KMP算法,一种用于高效字符串匹配的改进算法,通过next数组存储模式串局部匹配信息,以减少比较次数。作者给出了算法思想、next和nextval数组的计算以及实际的KMP函数实现,并展示了如何应用在主串和模式串的匹配中。

2118

被折叠的 条评论
为什么被折叠?



