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

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

猜你喜欢

转载自blog.csdn.net/qq_52269550/article/details/121361709