KMP算法 → 计算next数组

本文介绍了KMP算法中的核心部分——next数组,解释了next数组的含义和重要性,并详细阐述了如何根据模式串计算next数组。内容包括两种不同的定义方式,以及这两种方式如何得出一致的计算结果。同时,还给出了一个KMP算法应用的实例及解题思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【KMP算法简介】
KMP算法中的next数组仅取决于模式串本身,而与相匹配的主串无关。
KMP算法中的next数组,是KMP算法的核心。

KMP算法是由克努特(Knuth)、莫里斯(Morris)和普拉特(Pratt)共同设计实现的,因此简称KMP算法。此算法可以在
O(n+m)的时间数量级上完成串的模式匹配操作。其相对于BF算法的改进在于:每当失配时,无须回溯主串的指针,而是利用已经得到的“部分匹配”的结果将模式串向右“滑动”尽可能远的一段距离后,继续进行比较。这个滑动的距离就是由next数组确定的。

KMP算法本身并不复杂,主要分为两步:求next[ ]数组、匹配字符串。但绝大部分的文章把它讲混乱了,以致造成很多混淆。

【求next数组的算法】
求next数组 在KMP算法的众多实现中,有许多种定义next数组的方式。所以在使用和查看别人代码时,要特别注意KMP算法的next数组的定义,以免发生混淆。如:
• 严蔚敏《数据结构》将模式串下标从1开始计数,故定义next[1]=0,next[2]=1;
• 李春葆《数据结构》将模式串下标从0开始计数,故定义next[0]=-1,next[1]=0。

情况一: 模式串下标从1开始时求next数组的算法
若在KMP算法设计中,将
模式串下标从1开始计数,则定义next[1]=0,next[2]=1。那么求next数组的算法步骤为: (1)若第j-1位的字符与第x位的字符相等,则next[j]=x+1; (2)若直到第1位依然没有字符与第j-1位的字符相等,则next[j]=1
显然,若按严蔚敏《数据结构》中模式串的定义方式(即定义next[1]=0,next[2]=1),可得出模式串ababaaab的next数组如下:
-------------------------------------------------------
    j             1    2    3    4    5    6   7   8
------------------------------------------------------- 
                  a    b    a    b    a    a    a   b
-------------------------------------------------------
next[j]        0    1    1    2    3    4   2   2
-------------------------------------------------------

情况二:模式串下标从0开始时求next数组的算法
若在KMP算法设计中,将
模式串下标从0开始计数,则定义next[0]=-1,next[1]=0。那么求next数组的算法步骤为: (1)若第j-1位的字符与第x位的字符相等,则next[j]=x+1; (2)若直到第0位依然没有字符与第j-1位的字符相等,则next[j]=0
显然,若按李春葆《数据结构》中模式串的定义方式(即定义next[0]=-1,next[1]=0),可得出模式串abcabaa的next数组如下:
-------------------------------------------------
    j             0    1    2    3    4    5    6
------------------------------------------------- 
                  a    b    c    a    b    a    a
-------------------------------------------------
next[j]       -1    0    0    0    1    2    1
-------------------------------------------------

但这两种定义方式,不影响它们有一致的计算方法,即“
若第j-1位的字符与第x位的字符相等,则next[j]=x+1”(特别注意:在此判别过程中,所谓的第x位是由已经计算出的next[j-1] → next[0]间的若干值跳转抵达)。

个人喜欢采用李春葆《数据结构》中模式串的定义方式(即定义next[0]=-1,next[1]=0),并据此给出了如下图所示的求j=4时模式串元素b的next数组值的图例。

 


 

【研究生考试2015年第8题】
已知字符串s为“abaabaabacacaabaabcc”,模式串t为“abaabc”。采用KMP算法进行匹配,第一次出现“失配”( s[i]!=t[j] )时,i=j=5,则下次开始匹配时,i和j的值分别是(  
C )。
A. i=1,j=0          B. i=5,j=0          C. i=5,j=2          D. i=6,j=2

输出李春葆定义法next数组值的算法代码

#include<iostream>
using namespace std;

const int maxn=100;
int ne[maxn];

void getNext(string s) {
	int len=s.length(); //First of all, you must calculate the length of the string.
	int i=0, j=-1;
	ne[0]=-1;
	while(i<len) {
		if(j==-1 || s[i]==s[j]) {
			ne[++i]=++j;
		} else j=ne[j];
	}
}

int main() {
	string T;
	getline(cin,T);
	getNext(T);
	for(int i=0; i<T.length(); i++) {
		cout<<ne[i]<<" ";
	}

	return 0;
}


/*
input: ababaaababaa

output: -1 0 0 1 2 3 1 1 2 3 4 5
*/


【输出严蔚敏定义法next数组值的算法代码】

#include<iostream>
using namespace std;
 
const int maxn=100;
int ne[maxn];
 
void getNext(string s) {
	int len=s.length(); //First of all, you must calculate the length of the string.
	int i=0, j=-1;
	ne[0]=-1;
	while(i<len) {
		if(j==-1 || s[i]==s[j]) {
			ne[++i]=++j;
		} else j=ne[j];
	}
}
 
int main() {
	string T;
	getline(cin,T);
	getNext(T);
	for(int i=0; i<T.length(); i++) {
		cout<<ne[i]+1<<" ";
	}
 
	return 0;
}
 
 
/*
input: ababaaababaa

output: 0 1 1 2 3 4 2 2 3 4 5 6
*/


 


【参考文献】
https://blog.csdn.net/dark_cy/article/details/88698736
https://www.zhihu.com/question/21923021



 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值