KMP算法的理解

KMP的理解

前缀 和后缀的理解

主串: a b a b c a b c a c b a b
子串: a b c a c

KMP :利用比较过的信息,使子串不需要回溯,仅将字串向后滑动到一个合适的位置,并从这个位置开始与主串进行比较。

下面开始进行KMP匹配
第一次匹配:
a b a b c a b c a c b a b
a b c
是不是匹配到子串中的 c 就结束了,这个时候按照正常的思路是不是将字串向后移动2位,因为如果向后移动一位,如下图:a 是不是不可能等于 b ,那咱们肯定就不可能让他俩比较。
在这里插入图片描述
那我们将子串的比较向后移动2位,如下图:
在这里插入图片描述
接下来我们就该想想如何让计算机知道我们向后移动的个数那,别着急,我们再往下看看。

第二次匹配:
在这里插入图片描述

是不是到字串的 c 就结束了,这时候咱们应该往后移动多少那?

那咱们就看看匹配的字串 :a b c a c

想一想是不是应该找下在 a b c a 中从前面开始的字串,和从后面开始的字串中最大相同的子串。我们来看下,在 a b c a 中,显而易见,只有前面的a 和后面的 a 相同,那我们就将下一次子串移动到后面的这个a 上,是不是。

所以那,我们要如何得到假设在子串的每一个字母匹配失败后,应该向后移动的步长那?
当然,我们还是按照上面的方法,只不过我们会重新给他命名,叫部分匹配值。

前缀: 除最后一个字符以外,字符串的所有头部子串
后缀: 除第一个字符以外,字符串的所有尾部子串
部分匹配值:字符串的前缀和后缀的最长相等前后缀长度
eg:
在这里插入图片描述
在这里插入图片描述
得到next匹配值后,我们得到: 移动位数 = 已经匹配字符数 - 对应的部分匹配值

现在应该对前缀、后缀、部分匹配值、next理解了吧

next算法的理解

如何求next数组

方法1:

一. Next[j] : 为 j – 1 个字符串的(前缀和后缀相等的最大长度)+ 1

方法2:

二. 设当前待求的为next[n] (n>2) , next[n-1] = m

  1. 假如前面的n-1 个字符的 前 m个字符和后m个字符相同,则next[n] = m + 1,转到3
  2. 前 m个字符和后m个字符 不同的话,若m = 1 ,则next[n] = 1 ,转到3, 否则,令 m = m -1,观察该字符串的前 m-1个字符和后m-1个字符,若相同则转到1,否则继续2
  3. 结束本次求解的操作
    看看下面的例子:
    在这里插入图片描述
    在这里插入图片描述
    下面就理解下next算法
void next(String T, int next[]){//子串为 T,
	int i = 1, j = 0 ;// i 表示为next数组下标,j 表示为当前最大部分匹配值
	next[1] = 0 ;//规定第一个为next为0,数组下标从1开始
	//下方循环求解子串的next数值
	while(i < T.length){
		//第一种结果:如果
		if(j == 0 || T.ch[i] == T.ch[j]){
			++i;
			++j;
			next[i] = j;
		}
		else{
			j = next[j]; // 
		}
	}
}

从求解next数组算法中,我们知道该算法一共有两种情况:

  1. 当 T.ch[i] == T.ch[j] 的时候,next[i + 1] = next[i] + 1;
  2. 当 T.ch[i] ! = T.ch[j] 的时候,令j = next[j]

那我们在利用算法运行一下:子串 a b a b a a a b a b a a

在这里插入图片描述

  1. i = 1 , j =0 , next[1] = 0 因为 j = 0 ,进入if 语句中,i = 2, j = 1, next[2] = 1

在这里插入图片描述
2. 循环:T.ch[i] = T.ch[j] ?如上图,a != b, 则 j = next[j] = 0, 此时还不好看出
3. 循环: j = 0 ? 进入if语句, i = 3, j = 1,next[3] = 1
在这里插入图片描述
4. 循环: T.ch[i] = T.ch[j] ?如上图 :a = a , 则进入if语句, i = 4, j = 2,next[4] = 2
在这里插入图片描述
5. 循环: T.ch[i] = T.ch[j] ?如上图 :b = b , 则进入if语句, i = 5, j = 3,next[5] = 3
在这里插入图片描述
6. 循环: T.ch[i] = T.ch[j] ?如上图 :a = a , 则进入if语句, i = 6, j = 4,next[5] = 4

在这里插入图片描述
接下来重点来了

  1. 循环: T.ch[i] = T.ch[j] ?如上图: a ! = b , 则进入else:j = next[j] = 2

在这一步理解 j = next[j] ,

在这里插入图片描述

好了,到了这一步我们应该对next数组求解算法有个大概的理解,当然了,做题的时候应该用第一种方法,是比较快的。

KMP算法的理解

相信理解了next算法之后,这个算法就迎刃而解了,甚至你不理解next算法,知道next数组的作用也可以理解的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值