KMP算法的几种写法

简介

KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,因此人们称它为克努特—莫里斯—普拉特操作(简称KMP算法)。KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是通过一个next()函数实现,函数本身包含了模式串的局部匹配信息。KMP算法的时间复杂度O(m+n)

主串和字串和next数组都从零位置开始

#include<stdio.h>
#include<string>

int kmp(char* mainStr,char* subStr,const int* next) {
	int len1 = strlen(mainStr);
	int len2 = strlen(subStr);
	int i = 0, j = 0;
	while (i < len1&&j<len2) {//当珠串被遍历完或者字串被遍历完就结束也就也就意味着没匹配到或者匹配到了第一次出现的位置
		if (mainStr[i] == subStr[j]) {//当i和j位置相等往下走
			i++;
			j++;
		}
		else {//不相等的时候
			
			if (j == 0) {//当j以经在0上了说明主串i位置之前的字符都无法和字串匹配到只能让i下移
				i++;
			}
			else {//当j还没有为0说明主串i之前还可能存在着和字串可以匹配的位置
				j = next[j ];//由于next数组的性质我们选取要和主串i位置对比的下一个字串的j位置
			}

		}

	}
	return i-len2;//若是匹配成功返回在主串的位置
}

int main() {
	char mainstr[] = "abacbababdabaabca";
	char sub[] = "abaabc";
	int next[] = {0,0,0,1,1,2 };//求出next数组
	
	int ans = kmp(mainstr, sub, next);
	printf("子串在主串中的位置(从0开始)%d\n", ans);
	printf("验证:");
	for (int i = 0; i < strlen(sub); ++i) {
		printf("%c",mainstr[ans+i]);
	}

	return 0;
}

主串和字串和next数组都从1位置开始

#include<stdio.h>
#include<string>

int kmp(char* mainStr, char* subStr, const int* next) {
	int len1 = strlen(mainStr);
	int len2 = strlen(subStr);
	int i = 1, j = 1;
	while (i < len1&&j < len2) {

		if (j == 0 || mainStr[i] == subStr[j]) {
			i++;
			j++;
		}
		else {
			j = next[j];

		}

	}
	return i - j+1;//若是匹配成功返回在主串的位置
}

int main() {
	char mainstr[] = "0abacbababdabaabca";
	char sub[] = "0abaabc";
	int next[] = { NULL,0,1,1,2,2,3 };//求出next数组

	int ans = kmp(mainstr, sub, next);
	printf("子串在主串中的位置(从1开始)%d\n", ans);
	printf("验证:");
	for (int i = 0; i < strlen(sub)-1; ++i) {
		printf("%c", mainstr[ans + i]);
	}

	return 0;
}

重头戏计算next数组

因为目前都是默认从1开始的,我们求next也从一开始了

void getNext(char* subStr,int* next) {
	int i = 1, j = 0,len=strlen(subStr);//模拟串的前后缀i为后缀j为前缀
	next[1] = 0;//1位置默认为零
	while (i < len) {//求前后缀的匹配问题又回到了kmp

		if (j == 0 || subStr[i] == subStr[j]) {
			i++;
			j++;
			next[i] = j;
		}
		else {
			j = next[j];
		}
	}

}

求nextval

在next的基础上加上


void getNextVal(char* subStr,int* next,int* nextval) {
	int len = strlen(subStr);
	nextval[1] = 0;
	for (int i = 2; i < len; i++) {
		if (subStr[next[i]] == subStr[i]) {
			nextval[i] = nextval[next[i]];
		}
		else {
			nextval[i] = next[i];
		}
	}

}

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

肥学

感谢支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值