KMP算法

​ 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创作

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

newcatowen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值