深入理解Sunday算法(附上C++代码)

本文介绍了Sunday算法,一种类似于KMP算法的字符串匹配方法。在匹配失败时,Sunday算法根据主串中最后参与匹配字符的下一位在模式串中的位置来决定移动位数,从而提高效率。通过实例解析了算法的移动策略,并提供了C++实现代码。文章最后给出了一个实际应用示例,演示了如何使用该算法查找模式串在主串中的位置。
摘要由CSDN通过智能技术生成

2.Sunday算法
Sunday算法与KMP算法一样是从前往后匹配,在匹配失败时关注的是主串中参加匹配的最末位的下一位字符。
如果该字符没有在模式串中出现则直接跳过,即移动位数=模式串长度+1;
否则,其移动位数=模式串长度-该字符最右出现的位置(从0开始)=模式串中该字符最右出现的位置到尾部的距离+1
例:假定现在要在主串substring searching xiaowu中查找search。
1.刚开始时,把模式串与文本串左边对齐:
在这里插入图片描述

2.结果发现在第2个字符处发现不匹配,不匹配时关注文本串中参加匹配的最末位字符的下一位字符,即绿色的字符i,因为模式串search中并不存在i,所以模式串直接跳过一大片,向右移动位数=匹配串长度+1=6+1=7,从i之后的那个字符(即字符n)开始下一步的匹配。
在这里插入图片描述

3.结果第一个字符就不匹配,在看文本串中参加匹配的最末位字符的下一位字符,是“r”,他出现在模式串中的倒数第3位,于是把模式串向右移动3位(r到模式末尾的距离+1=2+1=3),使两个“r”对齐。
在这里插入图片描述

4.匹配成功
整个过程,我们只移动了两次就找到了匹配的位置,是因为Sunday算法的每一步移动量都比较大,效率很高。

代码:

#include <iostream>
#include <string>
using namespace std;
const int maxNum = 1005;
int shift[maxNum];
int Sunday(const string& T, const string& P) {
	int n = T.length();
	int m = P.length();
	// 默认值,移动m+1位
	for (int i = 0; i < maxNum; i++) {
		shift[i] = m + 1;
	}
	// 模式串P中每个字母出现的最后的下标
	// 所对应的主串参与匹配的最末位字符的下一位字符移动到该位,所需要的移动位数
	for (int i = 0; i < m; i++) {
		shift[P[i]] = m - i;
	}
	// 模式串开始位置在主串的哪里
	int s = 0;
	// 模式串已经匹配到的位置
	int j;
	while (s <= n - m) {
		j = 0;
		while (T[s + j] == P[j]) {
			j++;
			// 匹配成功
			if (j >= m) {
				return s;
			}
		}
		// 找到主串中当前跟模式串匹配的最末字符的下一个字符
		// 在模式串中出现最后的位置
		// 所需要从(模式串末尾+1)移动到该位置的步数
		s += shift[T[s + m]];
	}
	return -1;
}
/**
IN
at the thought of
though

OUT
7
**/
int main() {
	// 主串和模式串
	string T, P;
	while (true) {
		// 获取一行
		getline(cin, T);
		getline(cin, P);
		int res = Sunday(T, P);
		if (res == -1) {
			cout << "主串和模式串不匹配。" << endl;
		}
		else {
			cout << "模式串在主串的位置为:" << res+1 << endl;
		}
	}
	return 0;
}

本文参考:https://mp.weixin.qq.com/s?__biz=MzUyNjQxNjYyMg==&mid=2247486028&idx=1&sn=64c25776f40f46c5e267730741024f69&chksm=fa0e65cdcd79ecdbd11882a762a91f462d80e191778e2414f7276bae09ba5c7476398868b8fe&scene=21#wechat_redirect

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值