串匹配算法——KMP (algorithm for KMP)

串匹配算法——KMP (algorithm for KMP)

  • tips:
    我们知道字符串操作的不可避免的问题就是求出待匹配的字符串在主串中的位置(即首次出现的下标),目前已知的有两种主流的串模式匹配算法——暴力匹配和kmp模式匹配算法。

学习本节内容需要预备的知识(可以自行上网查阅哦)

  • 字符串的表示
  • 字符串的前后缀(不同位置)
  • KMP算法的原理
  • 什么是next数组
  • 什么是nextval数组(KMP的改进)
  • summary:(discrepancy of two method)
    moderate tactics:
methodviolent match
time complexityO(m*n)
space complexityO(1)
theoryMath each char in the main string which in the string wating for matching.If flase in this procedure the point in the main string will roll back and do it again in the correct position.

KMP tactics:

methodKMP
time complexityO(m+n)
space complexityO(m)
theoryMath each char in the main string which in the string wating for matching.If flase in this procedure the point in the main string will not rollback and go straight forever but the assistant string will goback the site sccording to the array that name is “next”.
  • Now that you have learned the idea of KMP and violent match algorithm. follows are two tactics’s realization for me with C++. I hope it will enhance you much.
  • violent match:
#include<bits/stdc++.h>
using namespace std;
#define maxn 1024
//暴力匹配
//匹配串在珠主串进行匹配
//成功两个串的指针后移
//失败的话主串指针跑到本次开始匹配的下个位置,匹配串指针回到本串的起始位置
//当主串或匹配串任意一个的指针超过其串长就退出匹配
//如果匹配串的指针大于串长匹配成功返回开始匹配的位置(匹配成功)
//否则匹配失败返回-1 
char *s,*t;

//暴力匹配算法 
int violent_match(char *mainStr,char *assistantStr);
/*
abcabdef
abd 
*/

int main(){
	s=new char[maxn];
	t=new char[maxn];
	scanf("%s\n%s",s,t);
	int pos=violent_match(s,t);
    if(pos==-1) printf("匹配失败了哦!");
	else printf("匹配字符串在主串中的首次出现的位置是:%d",pos); 
	return 0;
} 

int violent_match(char *mainStr,char *assistantStr){
	int lens=strlen(mainStr);
	int lent=strlen(assistantStr);
	int i=0,j=0;
	while(i<lens&&j<lent){
		if(s[i]!=t[j]){
			i=i-j+1;
			j=0;
		}else {i++; j++;}
	} 
	if(j>=lent) return i-lent;//成功 
	else return -1;//失败 
}
  • KMP
//kmp算法的实现

#include<bits/stdc++.h>
#define maxn 1024
using namespace std;

char *s, *t;
int *my_next;
int len;
int *next_val;

//获得 next数组
void getNext(int *next_arr);
//kmp
int kmp();
void show(int *next_arr);
void getnextVal() {//next数组的优化,大部分考试不要求掌握 
	next_val = new int[maxn];
	next_val[0] = -1;
	cout<<"nextval 数组入下:"<<endl;
	for (int i = 1; i < len; i++) {
		if (t[i] == t[my_next[i]]) next_val[i] = next_val[my_next[i]];
		else next_val[i] = my_next[i];
	}
	show(next_val);
}

int main() {
	s = new char[maxn];
	t = new char[maxn];
	my_next = new int[maxn];
	memset(my_next, 0, sizeof(int)*maxn);
	scanf("%s\n%s", s, t);
	cout << s << endl;
	cout << t << endl;
	len = strlen(t);
	getNext(my_next);
	cout<<"next 数组如下:"<<endl; 
	show(my_next);
	getnextVal();
//	int flag=kmp();
//	if(!flag) cout<<"匹配失败!"<<endl;
//	else cout<<"成功且位置是:"<<flag<<endl;
	return 0;
	/*
	asdsaabaabc
	abaabc
	*/
}

void show(int *next_arr) {
	for (int i = 0; i < len; i++)
		cout << next_arr[i] << " ";
	cout << endl;
}

int kmp() {
	int i = 0, j = 0;
	int length1 = strlen(s);
	int length2 = strlen(t);
	while (i < length1 && j < length2) {
		if (j == -1 || s[i] == t[j]) {
			i++;
			j++;
		} else j = my_next[j];
	}
	cout << "i is:" << i << endl;
	cout << "j is:" << j << endl;
	if (j >= strlen(t)) return i - length2;
	else return -1;
}

void getNext(int *next_arr) {
	int i = 0, j = -1;
	next_arr[0] = -1;
	while (i < len) {
		if (j == -1 || t[i] == t[j]) {
			i++;
			j++;
			next_arr[i] = j;
		} else j = next_arr[j];
	}
}
/*
输入:
abcacssxn
sxn
输出:
abcacssxn
sxn
-1 0 0
i is:9
j is:3
成功且位置是:6
*/

/*
abaabaabacacaabaabcc
abaabc
*/
  • KMP的python实现
class KmpClass:
    def __init__(self) -> None:
        self.next = []

    def get_next(self,mode_str):
        next = [-1] * len(mode_str)
        i = 0
        j = -1
        # 因为循环中第一个判断语句时是先下标增加然后再赋值,这里不小于长度减去1的话可能会有下标越界的错误
        while i < len(mode_str) - 1: 
            if j == -1 or mode_str[i] == mode_str[j]: # 找到了前后相等的往前进
                i += 1
                j += 1
                next[i] = j
            else: # 没有找到就让j滚回到上次找到的地方
                j = next[j]
        self.next = next
    
    def kmp_match(self,match_str,mode_str):
        i = j = 0 # 从两个串的起始位置开始匹配
        while i < len(match_str) and j < len(mode_str):
            if j == -1 or match_str[i] == mode_str[j]: # 这里有 -1 主要因为next数组中可能存在-1
                i += 1
                j += 1
            else:
                j = self.next[j]
        if j < len(mode_str):
            return -1
        else:
            return i - j
                

I confirm that the goal of being admitted to graduate school will come true next year! come on!!!

  • 2022/5/30
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

SweetCode

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值