KMP算法中的next数组建立

文章详细介绍了KMP算法中的next数组的用途和理解,next数组用于在匹配失败时确定无需回退的“重新匹配”字符数,提高字符串匹配效率。作者指出next数组是字符串的最长公共前后缀长度,并解释了不同代码实现中的递归思想。文章提供了构建next数组的代码示例,并解答了关于长度作为下标和死循环条件的疑惑。
摘要由CSDN通过智能技术生成

最近在学习这 K M P KMP KMP时,总感觉 n e x t next next数组的建立有些稀里糊涂,然后自己就看了一堆视频,最后发现 K M P KMP KMP每个人的写法不尽相同,更是把我绕晕了。故写这篇文章就是为了总结一下高手们的代码

n e x t next next数组的用途

next数组的建立主要是 K M P KMP KMP算法在匹配失败的时候,回去看最后一个匹配的字符它所对应的next数值—代表子串中我们能跳过”重新匹配“的字符个数

由于next数组的这里特性,就不再需要回退在主串上的指针,只需要一次主串的遍历就可以完成匹配,效率自然比之前的暴力算法高很多

n e x t next next数组的理解

next数组其实理解起来很简单就是字符串的最长公共前后缀的长度,比如 a b a b abab abab a b b a abba abba的最长公共前后缀的长度分别是2和1。但是为什么代码看起来很抽象,主要是因为 K n u t h Knuth Knuth M o r r i s Morris Morris P r a t t Pratt Pratt三位大佬在实现 n e x t next next数组时使用了递归思想(里面‘回退’)

n e x t next next数组建立的总思想

如果下一字符依然相同的话,代表可以构成一个更长的前后缀,长度+1即可
如果下一字符不同的话,就寻找该字符串的前缀的最长公共前缀

n e x t next next数组代码理解

int main() {
	string str, str1;
	int kmp[100] = {0}, next[100] = {0};
	while (cin >> str) {
		int n = str.length();
		int i  = 1;
		int k = 0;
		while ( i <= n - 1) {
			if ( str[i] == str[k]) {
				kmp[i] = ++k;
				i++;
			} else {
				if ( k == 0) {
					kmp[i] = 0;
					i++;
				} else {
					k = kmp[k  - 1 ];
				}
			}
		}
		for ( int i = 0 ;  i <= n - 1 ; i++ ) {
			cout << kmp[i] << " ";
		}
	}
}

这里的k就是代表当前字符串的长度
主要难点就是

                                       k = kmp[k  - 1 ];

很多人感到很怪异的地方就是kmp[k - 1 ]?
k代表的是长度为什么放在kmp的下标中呢?长度怎么可以当做下标?

以‘ababc‘为例:
首先 a b a b abab abab的长度是 2 2 2,会发现 2 − 1 2-1 21就是前缀‘ a b ab ab’的 b b b所在的下标,所以
k k k代表的长度, k − 1 k-1 k1代表的是最长前后缀中前缀最后一个元素的下标,然后再
根据

如果下一字符不同的话,就寻找该字符串的前缀的最长公共前缀

那么就自然的写出来

                                     k = next[k-1]

还有人疑惑

                                         k == 0

其实 k = n e x t [ i ] k=next[i] k=next[i]str[i]!=str[k]的情况下死循环,然而根据我们所讲单独一个字符是没有前后缀的,所以停止循环的条件,所以到第一个字符的时候要让 t a ta ta停止

还有一种写法就是当k从1开始算起,其实原理是一样的:

void get_next(string T, int *next) {
	int i, k;
	i = 1;
	k = 0;
	next[100] = {0};
	while ( i < T[0]) //T[0]存放长度
	 {
		if ( k == 0 || T[i] == T[k]) {
			++i;
			++k;
			next[i] = k;
		} else {
			k = next[k];
		}
	}
}

大家可以想一下为什么这里是

                                        k = next[k]




记得刚在所说的长度和下标转换吗?
当时由于下标是从 0 0 0算起,所以最长公共长度为 1 1 1时,下标是 0 0 0
但是这里下标是从 1 1 1算起,所以最长公共长度为 1 1 1时,下标是 1 1 1

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值