【算法】线性表-串的匹配算法


前言

串是一系列字符以线性关系连接而成的数据结构,其基本实现靠的还是线性表,关于它的数据结构在这里就不赘述了,本章主要讲关于字符串匹配很重要的两个算法,一个是BF另一个是KMP

一、BF算法

一般字符串都喜欢把第一个位置空出来存放长度之类的,这里我们默认数据从数组下标为1处开始。BF算法的过程就是逐个校对字符,出现错误后就回到第一个校对字符的下一位,首先把位置给到i和j,当下标不超过字符串长度时,不停地对比字符,对比成功下标+1,对比失败子串下标归零,模板下标回到上次比较位置地下一个位置,循环结束后判断j的值,如果等于子串长度,说明退出循环是因为找到了子串,否则是因为模板已经遍历完了,返回对应的值就好

int index_BF(SString S, SString T, int pos){
	// S是模板字符串,T是子串,pos是指在S的第几个字符开始匹配
	int i = pos;
	int j = 1;
	while(i < S.length && j < T.length){
		if(S[i] == T[j]){
			// 匹配正确,继续对比下一个字符
			++i;
			++j;
		}else{
			// 匹配错误下标更新
			i = i - j + 2;
			j = 0;
		}
		// 成功找到子串,返回子串在模板中第一个位置的下标
		if(j == T.length-1) return i - T.length + 1;
		return 0;
	}
}

二、KMP算法

KMP算法就是不移动模板的游标,不同位置匹配失败之后子串游标的调整不一样,以此来达到提高效率的目的,具体思路就不说了大家有兴趣可以参考网上大佬们的视频(这里是讲代码的),这里直接上代码

void get_next(SString T, int &next[]){
	int i = 1, j = 0;
	next[i] = 0;
	while(i < T[0]){	// T[0]表示这个串的长度
		if(j == 0 || T[i] == T[j]) next[++i] = ++j;
		else j = next[j];
	}
}

int index_KMP(SString S, SSreing T, int pos){
	int i = pos, j = 1;
	while(i < S[0] && j < T[0]){
		if(j == 0 || S[i] == T[j]){
			++i;
			++j;
		}else j = next[j];
	}
	if(j == T[0]) return i - T[0] + 1;
	return 0;
}

这里还有一个关于next数组的优化,核心思想就是,我当前字符匹配失败了,回溯过去,如果回溯的位置的字符和我当前匹配的字符一样,那就说明百分百匹配失败,那我直接拿他的回溯位置作为我的回溯位置就好了

void get_nextval(SString T, int &next[]){
	int i = 1, j = 0;
	next[i] = 0;
	while(i < T[0]){	// T[0]表示这个串的长度
		if(j == 0 || T[i] == T[j]) next[++i] = ++j;
		else j = next[j];
	}	//		前面的代码和next的一样,关键在于下面的更新
	for(i = 1; i < T[0]; ++i){
		if(T[i] == T[next[i]]) next[i] = next[next[i]];
	}
}

跳转系列文章目录


  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值