kmp算法

终于还是踏上了算法这条不归路,记录一下做题的历程


KMP算法

用以解决串匹配问题,蛮力算法的缺点在于每次匹配失败后向后移动一个字符继续匹配继续匹配。尽管第一次匹配是有必要的,但后续的大量重复匹配就没有必要了。
蛮力算法,eg:
在这里插入图片描述
kmp算法的大致过程:
在这里插入图片描述next表的建立是基于模式串中已匹配的串中相似的前缀和后缀,简单的说,就是已匹配前缀中的前缀和后缀有相同部分。大致过程如下(以上图为例):

在这里插入图片描述注:若前缀中含有多个相似的前缀和后缀,kmp会选择右移最小的那个(相对安全),同时也表明舍弃的那部分对齐位置确实是不值得对齐的这一不变性。

一般地,会将next [ 0 ]设置为-1,可以理解为在字符串秩为-1处逻辑上存在一个假想的哨兵 (实际上不存在)—— " * " 通配符,用以匹配所有的子串,来满足第一次的匹配(使j > 0),而使j>0的原因是要避免已匹配串中相似前缀和后缀为空集的情况。如下图

在这里插入图片描述

next表构建算法:

int * buildNext(char * P){			// 构造模式串P的next[]表
	size_t m = strlen(P), j = 0;			// “主”串指针
	int * N = new int[m];			// next[]表
	int t = N[0] = -1;			// 模式串指针( p[-1] 通配符)
	while(j < m - 1){
		if(0 > t || P[j] == P[t]){			// 匹配
			N[++j] = ++t;
		}
		else{			// 失配
			t = N[t];
		}
	}
	return N;
}

kmp主算法:

int match(char * P, char * T){
	int * next = buildNext(P);			// 构造next表
	int n = (int) strlen(T), i = 0;			// 文本串指针
	int m = (int) srtlen(P), j = 0;			// 模式串指针
	while(j < m && i < n){			// 自左向右,逐个比对字符
		if(0 > j || T[i] == P[j]){			// 若匹配
			i++;			// 携手共进
			j++;
		}
		else{			// 否则,P右移,T不回退
			j = next[j];
		}
	}
	delete [] next;			// 释放next表
	return i - j;
}

习题

https://leetcode-cn.com/problems/implement-strstr/

本文参考《数据结构》| 邓俊辉

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值