串的模式匹配算法

目的:查找主串中所含字串的位置

两种算法:

1.BF(暴力破解法)

2.KMP

BF:字串从头开始依次比较

代码:

#include<stdio.h>
#define XAZSIZE 100
#define error -1
typedef struct{
	char ch[MAXSIZE+1];//加一的原因是舍弃ch[0]的空间,
//将ch[1]作为第一个元素,后面便于理解。 
	int length;
}SString;

int index_BF(SString S,SString T){//S为主串。T为字串 
	int i=1,j=1;
	while(i<=S.length&&j<=T.length]<=T.length){
		if(S.ch[i]==T.ch[j]){
			i++;
			j++;
		}else{
			i=i-j+2;
			j=1;//匹配失败,j回到初始值,i回到初始值再向前移动一格 
		}
	}
	if(j>=T.length) return i-T.length;//匹配成功,返回字串在主串中的地址
	else return error;//匹配失败 
}

int main(){
	return 0;
}

下面介绍KMP模式算法:原理b站天勤

这里简单记叙求next数组:

求next数组时忽略主串,只看模式串(字串),假如子串元素个数是5,构造一个a[5]数组(0号位忽略是数组下标等于逻辑上的元素位置)。则先看子串前两位,公共前后缀的大小为0(公共前后缀不能是本身),a[2]记为1,可以得出任意字串的next数组a[2]=1.意思是当字串第二位与当前主串就不匹配时,字串下一次比较时从0+1=1号位开始比较。再看字串前两位,假如是aa,因此公共前后缀为1,则a[3]记为0+1=1,意思是当字串的前两位与主串匹配,而第三位与主串不匹配时,下一次匹配直接从子串的的第一位开始匹配。

所以a[1]=0是什么意思呢:

在任意子串中都有a[1]=0,其含义和next数组其他位置稍有区别,意思是当第一位就不匹配时,下一次匹配从子串的一号位与主串的下一位开始比较。而其他情况下下一次匹配是从主串的下n位开始比较,这里n是当前匹配中前n位主串与子串相同。即next数组的下标。

next数组的代码原理非常精妙,参考b站KMP算法之求next数组代码讲解(凡三爱学习

代码

#include<stdio.h>
#define MAXSIZE 100
#define error -1
#include<stdlib.h>
typedef struct{
	char ch[MAXSIZE+1];//加一的原因是舍弃ch[0]的空间,
//将ch[1]作为第一个元素,后面便于理解。 
	int length;
}SString;


//BF算法 
int index_BF(SString S,SString T){//S为主串。T为字串 
	int i=1,j=1;
	while(i<=S.length&&j<=T.length){
		if(S.ch[i]==T.ch[j]){
			i++;
			j++;
		}else{
			i=i-j+2;
			j=1;//匹配失败,j回到初始值,i回到初始值再向前移动一格 
		}
	}
	if(j>=T.length) return i-T.length;//匹配成功,返回字串在主串中的地址
	else return error;//匹配失败 
}

//KMP算法

int* GetNext(SString T){
 	int i=1;
 	int*next=(int*)malloc((MAXSIZE+1)*sizeof(int));
 	next[1]=0;
 	int j=0;
 	while(i<T.length){//这里<或者<=都可以,因为T.c的最后一个元素是什么与next数组无关 
 		if(j==0||T.ch[i]==T.ch[j]){
 			i++;
 			j++;
 			next[i]=j;
		 }else{
		 	j=next[j];
		 }
	 }
	 return next;
 }

 int index_KMP (SString S,SString T,int pos){
 	int i=pos;
 	int*next;
	int j=1;//pos指针确定了从主串的第几位之后开始查找 
	next=GetNext(T);//得到next数组 
 	while(i<=S.length&&j<=T.length){
 		if(j==0||S.ch[i]==T.ch[j]){//j==0的情况是对应子串与主串在第一位就不匹配的情况,
		 //此时j=next[1]=0,则下一次进入循环是主串向下移动一位,子串从头开始。 
 			i++;
 			j++;
		 }else{
		 	j=next[j];
		 }
		 if(j<=T.length)return error;//匹配失败
		 else return i-T.length; 
	 }
 } 
 
 
int main(){
	return 0;
}

现在介绍一下next数组的改进版,nextval数组,

 

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值