手撕KMP的next数组求法,真正理解next数组的求法

一)先理解一些概念

1.写kmp之前,需要先了解:

字符的前缀与后缀   部分匹配值【这里就不说了哈】

2.利用部分匹配值,就可以做到主串不会回溯,此时

子串j需要移动 = 已匹配的字符数 - 对应的部分匹配值,表示为

move=j -next[j-1] 【看这里是next[j-1],这样写代码多麻烦,所以我们把next数组整体右移一位(这也是为什么next[0]=-1的原因)】

这样最终形式就是: j=next[ j ];

二)求next数组

求next[j+1]会有两种情况:

1.a[i]==a[j], 那么 next[j+1]=next[j]+1;

2.a[i]!=a[j],此时需要回溯,让j=next[j]后,再让a[i]与a[j]比较

见图例:

 

#include<iostream>
#include<string>
using namespace std;
class chars_match {
	char *mainstr;
	char *substr;
	int* next;
	int len_sub,len_main;
public:
	chars_match(){}
	chars_match(char mainstr[], char substr[]) {
		this->len_sub=strlen(substr);
		this->len_main = strlen(mainstr);//得到主串·子串的长度
		this->mainstr = mainstr;
		this->substr = substr;
		next = new int[len_sub];
	}
	int kmp() {
		getnext();//获取next数组
		int i = 0, j = 0;
		while (i < len_main && j < len_sub) {
			if (j == -1 || mainstr[i] == substr[j]) {
				i++; j++;
			}
			else {
				j = next[j];
			}
		}
		if (j >= len_sub)return i - len_sub;
		else return -1;
	}
	void getnext() {//求next数组时也是不回溯滴!i一直往前走
		int j = -1, i = 0;
		next[0] = -1;
		while (i < len_sub - 1) {
			if (j == -1 || substr[i] == substr[j]) {
				i++; j++;
				next[i] = j;
			}
			else {
				j = next[j];
			}
		}
	}
};
int main() {
	char mainstr[] = "wymlvzhanghaojieaaaabfasda";
	char substr[] = "aaaab";
	chars_match* kmp = new chars_match(mainstr, substr);
	cout << kmp->kmp() << endl;
	//int a[] = { 1,2,3,4,5 };
	//int* b = a;
	//cout << sizeof(b)<<sizeof(a[0]) << endl;
	//cout << sizeof(a) / sizeof(*a) << endl;    //这是之前写的获取数组长度的方法,感juer比较有用
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值