C语言——KMP和BF算法实现模式匹配

模式匹配

给定主串S=“s1s2…sn”和模式串T=“t1t2…tn”,在S中寻找T的过程称为模式匹配。如果匹配成功,返回T在S中的位置;如果匹配失败,返回-1。
关于具体的算法原理和代码实现,这里推荐三个视频,视频中的图解可帮助快速理解算法原理。
懒猫老师-数据结构-(13)字符串匹配-BF算法(模式匹配)-哔哩哔哩
懒猫老师-数据结构-(14)字符串匹配-KMP算法1(模式匹配)-哔哩哔哩
懒猫老师-数据结构-(15)KMP算法2-next数组(模式匹配,字符串匹配)-哔哩哔哩

BF匹配算法描述:
1.在串S和串T中设比较的起始下标i和j;
2.循环直到S或T的所有字符均未比较完:
(1)如果S[i]==T[j],继续比较S和T的下一个字符;
(2)否则,将i和j回溯,准备下一趟比较;
3.如果T中所有字符均比较完,则匹配成功,返回匹配的起始比较下标;否则,匹配失败,返回-1;

KMP匹配算法描述:
1.在串S和串T中分别设比较的起始下标i和j
2.当S或T的所有字符均为比较完,则循环
(1)如果S[i]==T[j],继续比较S和T的下一个字符
(2)否则,将j向右滑动到next[j]位置,而i不变;(BF算法中是i移动到i-j+1,j直接回溯到0开始)
(3)如果j=-1,则将i++,j++,准备下一趟比较。
3.如果T中所有字符均比较完毕,则返回匹配的起始下标(i-j),否则返回-1(匹配失败)
难点:求next数组
1.当j=0时,next[j]=-1;(无条件赋初值,-1表示不进行字符比较,所以在算法中,当j=next[j]=-1时,需要i++)
2.就j>0时,next[j]的值为:模式串的位置从0到j-1构成的串中所出现的首尾相同的子串的最大长度
3.当无首尾相同的子串时,next[j]=0.(0表示从模式串头部开始重新比较) 。

代码如下:

#include<iostream>
#include<string.h>
using namespace std; 
int BF(char S[],char T[]){
 	int i,j=0;
 	while(S[i]!='\0'&&T[j]!='\0'){
 		if(S[i]==T[j]){
 			i++;
			j++;
		 }
		else{
		 	i=i-j+1;
		 	j=0;
		}
	}
	 if(T[j]=='\0'){
	 	return (i-j+1);
	 }
	 else return -1;
 }

void Next(char *T,int *next){//求next数组,递归求解(只对模式串进行处理) 
 	int j=-1;//前缀 
 	int i=0;//后缀 
 	next[0]=-1;//next[0]无条件赋初值为-1  
 	while(i<strlen(T)){
 		if(j==-1||T[i]==T[j]){
 			i++;
 			j++;
 			next[i]=j;
		}
		else{
		 	j=next[j];
		}
	}
}

int KMP(char S[],char T[]){
 	int i,j=0;
 	int next[strlen(T)];
 	Next(T,next) ;//根据模式串T,初始化next数组 
 	while(i<strlen(S)&&j<strlen(T)){//不能写成S[i]!='\0'&&t[j]!='\0',因为在KMP中j的值有可能是-1,会造成数组越界的情况 
 		if(j==-1||S[i]==T[j]){
 			i++;
 			j++;
		 }
		else{
		 	j=next[j];
		}
	}
	if(j==strlen(T)){ //最后退出循环的j的值等于模式串的长度,说明匹配成功 
	 	return i-j+1;//返回匹配成功的第一个字符位置 
	}
	else return -1;
}

int main(){
 	char S[100],T[100]={'\0'};//定义两个字符串S和T 
 	cout<<"输入字符串S和T:"<<endl;
	cin>>S;
	cin>>T;
	cout<<"1.用BF算法:主串和子串在第"<<BF(S,T)<<"个字符处首次匹配"<<endl;
	cout<<"2.用KMP算法:主串和子串在第"<<KMP(S,T)<<"个字符处首次匹配"<<endl;
	return 0;
} 

在这里插入图片描述

算法分析: 设串S长度为n,串T长度为m,在匹配成功的情况下:
1.BF算法: 最好情况:不成功的匹配都发生在串T的第1个字符。 最坏情况:O(n+m) 平均复杂度:O(n×m)
2.KMP算法: 包括求next数组O(m)和算法循环O(n)两部分 O(m+n)

这个代码经过试验,可以完整运行,至于算法的详细讲解,可以去B站看上面的视频,加深了解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小王不熬夜.com

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

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

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

打赏作者

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

抵扣说明:

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

余额充值