字符串经典匹配算法之Sunday算法

背景知识回顾

之前的文章中讲了字符串匹配问题中的单模匹配问题,即从一段文本串中找到另一个字符串是否出现过。母串(文本串)是指要从哪个字符串中查找,模式串指的是要查找哪个字符。之后介绍了暴力匹配算法,即从文本串中逐位向后和模式串比较。此外还介绍过KMP匹配算法,这种算法适合处理流式字符。

本文介绍Sunday匹配算法

Sunday算法理论介绍

假设文本串S和模式串T匹配的过程中遇到如下情况,发现失配:
在这里插入图片描述
此时文本串匹配结果的下一位为a, 那么可以从模式串从后往前寻找‘a’这个字符,发现其在倒数第4位第一次出现,此时可以将模式串向后移动4个位置。 ‘a’对齐的这个位置称为黄金对齐位。
在这里插入图片描述
看此时文本串对应位置和模式串是否匹配,发现还不匹配,而且文本串的下一位为字母‘b’, 那么从模式串中从后往前寻找‘b’这个字符,发现其在倒数第8位,所以可以将模式串向后移动8个位置。

不断重复上面的过程,直到模式串和文本串完全匹配。

如果可以提前记录模式串中的每个字符,在模式串的倒数第几位出现,那么对于一个新的字符,就可以马上判断应该将模式串向后平移几位。

此外如果移动的过程中,发现文本串的下一位在模式串中从来没有出现过,此时可以设置模式串的一个虚拟位置-1,该位置和任何一个字符都能匹配。这样就可以使算法不需要额外判断。

Sunday算法代码实现

int sunday(const char *text, const char *pattern) {
	#define BASE 256
	int n = strlen(text), m, last_pos[BASE];
	//last_pos的每一个索引表示一个字符,因为字符本身就能通过ascll码表示为整数。
	//last_pos的值表示pattern中的元素在的哪一位出现

	for (int i = 0; i < BASE; i++) last_pos[i] = -1; //默认为设置-1位置
	for (m = 0; pattern[m]; m++) last_pos[pattern[m]] = m;  
	for (int i = 0; i + m <= n; i += (m - last_pos[text[i + m]])) {
		//如果没匹配成功,那么text的索引i向后移动 m - last_pos[text[i + m]] 位,m为模式串的长度

		int flag = 1;
		for (int j = 0; j < m; j++) {
			if (text[i + j] == pattern[j]) continue;
			flag = 0;
			break;
		}
		if (flag) return i;
	}
	return -1;
}

Sunday算法应用场景

Sunday算法适合在一大串长文本中寻找一个比较短的字符串是否出现过。

极端情况下Sunday算法的时间复杂度可以降低到O(n / m), n为文本串长度,m为模式串长度。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值