C Language 串 - BF算法&&KMP算法(十一)

本文详细介绍了BF暴力破解算法和KMP算法在顺序串子串匹配中的应用,包括BF的暴力搜索策略与KMP算法的高效next数组求解。通过实例演示了如何查找子串位置并优化主串元素,重点讲解了KMP算法中next数组的作用和计算方法。
摘要由CSDN通过智能技术生成

因为是BF和KMP算法的讲解,所以这里以顺序串为例讲解。

  • 定义顺序串:
#define MaxSize 20
//定义数字串 
typedef struct SqString{
	char data[MaxSize];
	int length;
}SqString;
//初始化
void initStr(SqString &s){
	s.length = 0;
} 
  • 创建字符串
#include<iostream>
using namespace std;
//创建字符串
void strAssign(SqString &s){
	char x ;
	do{
		cin>>x;
		if(x == '0'){
			break;
		}
		s.data[s.length++] = x;  //表示用户自己输入字符串
	}while(true);
	printf("结束");
}
  • 输出字符串
//输出字符串 
void dispStr(SqString &s){
	int len = s.length , index = 0;
	
	for(;index < len;){
		printf("%3c",s.data[index++]);
	}	
}
子串模式匹配:

简单介绍一下思路,使用BF算法其实就是暴力破解,就是一个个去比对一个个去判定是否是相等

  • BF暴力破解算法:

在这里插入图片描述

//查找子串位置
int getStrPos(SqString s1 , SqString s2){
	//如果子串长度大于匹配长度,直接返回失败	
	if(s1.length < s2.length){
		return -1;
	}
	
	int indexi = 0 , indexj = 0 , indexk = 0 , index = -1;
	bool flag = false;
	for(;indexi < s1.length ; indexi++){
		for(indexj,indexk = indexi;indexj < s2.length;indexj++,indexk++){
				if(s1.data[indexk] == s2.data[indexj]){
					if(!flag){    //说明如果是第一次匹配成功进来,记录下最初的索引位置,当全部匹配成功就返回最初的索引位置。
						index = indexi;
					}
					flag = true;
				}else{
					flag = false; //查找不到直接归位
					index = -1; //查找不到直接归位
					break;
				}					
			}
		}	
		return index;
	}

在这里插入图片描述

  • 当找不到子串的时候会匹配失败
    在这里插入图片描述

  • 替换主串元素值:

//替换主串元素
void repStr(SqString &s1 , int index , SqString s3) {
	int i = 0;
	if( s1.length - index < s3.length) {
		s1.length = s1.length - index + s3.length; //长度不够的话就添加长度
	}
	for(i; i<s3.length; i++) {
		s1.data[index++] = s3.data[i];
	}
}
  • MKP算法求解:

补充:KMP算法的关键就是指针不再回溯了,然后可以直接通过记录next[j]的值进行模式串的匹配。

对应的index和next[j]的关系如下:
在这里插入图片描述
关于KMP算法其实只需要研究模式串就足够了,next[j]的求法,是指当index指向指定位置的时候,查看前面有多少匹配的元素,例如当index=5的时候,index = 3 和 index = 4 与 index = 0 和 index = 1相等,这就得出结论k -1 = 2,=>k求出来=3,所以next[j]的值求出来就等于3

在这里插入图片描述
使用笔算模拟了整个操作流程过程,这里是根据书上给出的j = 0,k=-1开始的,条件判断为k==-1 || s.data[j] == s.data[k],否则的话,k就后退一步(其实这个地方有一丝不理解的地方就是对应的next[j]的值都会少1,小编写的条件是j是从1开始的,k是从0开始的,然后条件判断改成k == 0 || s.data[j] == s.data[k])其他的还是没有变的

实现的代码如下

  • 求next数组的算法:
//根据模式串,求出next数组
void getNext(SqString s , int next[]){
		int j = 1 , k = 0;	
		next[0] = -1;
		while(j<s.length){
			if(k == 0 || s.data[j] == s.data[k]){
				k++,j++;
				next[j] = k;
			}else{
				k = next[k];
			}
		}
	} 
  • KMP算法
//KMP算法
int KMPIndex(SqString s1 , SqString s3 ){
	//如果模式串大于主串 
	if(s3.length > s1.length){
		printf("模式串长度高于主串,匹配结束!");
		return -1;
	}
	
	int next[MaxSize] , i = 0 , j = 0;
	getNext(s3,next);
	while(i < s1.length && j<s3.length){
		if(j == 0 || s1.data[i] == s3.data[j]){
			i++;
			j++;
		}else j = next[j];
	}
	
	if(j >= s3.length){
		printf("匹配成功");		
	}else{
		printf("匹配失败");
	}
}	

最终结果展示:

在这里插入图片描述

  • 匹配失败结果:

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值