字符串匹配算法

字符串匹配:

在匹配串中寻找模式串是否出现,并返回模式串的位置。注意和最长公共子序列相区别(LCS: Longest Common Substring)。

常用的字符串匹配算法:

假设匹配串长度为m,模式串长度为n。

暴力匹配Brute Force算法:

首先将匹配串和模式串左对齐,然后从左向右一个一个进行比较,如果不成功则模式串向右移动一个单位重新比较。速度最慢。最不理想的情况下,时间复杂度为O(m*n)。

KMP算法:

KMP 的思想是这样的:
利用不匹配字符的前面那一段(匹配)字符的最长前后缀来尽可能地跳过最大的距离。
比如,
匹配串为xbaxbaxbay
模式串为baxbay

匹配到如下状态:
匹配串:xbaxbaxbay
模式串: baxbay
发现在y之前的字符串都匹配了,找到其最大相等前后缀为ba。x和y虽然不匹配,但是对于匹配串,x之前的ba和模式串的前缀ba一定匹配上了,所以可以移动到如下状态:
匹配串:xbaxbaxbay
模式串: baxbay
此时从模式串前缀ba之后的x开始和匹配串进行比较。这个操作利用最大相等前后缀跳过了一段距离,减小了复杂度,这就是KMP。
B站上小哥讲的很好:https://www.bilibili.com/video/av3246487?from=search&seid=5460317095667529595
那么如何寻找最大相等前后缀?
我们不知道在哪里会匹配失败,所以我们希望结果是一个数组:在模式串x处失败时,访问这个数组的x处元素,能够得到最大相等前后缀长度。

首先初始化一个长度为n的数组,两个指针i和j,i指向数组首部,j指向数组第二个元素,数组首部元素初始化为0。
一开始,如果i和j不相等,数组计入0,同时后移j。重复这个步骤直到i和j相等。
如果i和j相等,数组存入i+1的值,i和j一起右移;如果i和j从相等变为不相等,i等于它指向数组元素之前的数组元素(前驱);如果i和j从不相等变为不相等,,数组计入0,同时后移j。
构建这个数组时间复杂度是O(n)。

Sunday算法

Sunday算法从前往后匹配,在匹配失败时关注的是主串中参加匹配的最末位字符的下一位字符。

  • 如果该字符没有在模式串中出现则直接跳过,即移动位数 = 模式串长度 + 1;
  • 否则,其移动位数 = 模式串长度 - 该字符在子串最右出现的位置(以0开始) = 模式串中该字符最右出现的位置到尾部的距离 + 1。
    详细的可以看https://blog.csdn.net/q547550831/article/details/51860017
int Sunday(string const &str, string const & substr) {
	int sz = str.size(), subsz = substr.size();
	int i = 0, j = 0;
	while(i<sz&&j<subsz) {
		while (j < subsz) {
			if (str[i + j] != substr[j]) { //字符串匹配失败,进行移动
				int k = 0;
				if (i + subsz >= sz) break;
				while (k<subsz && str[i + subsz] != substr[k]) 
					k++;
				if (k != subsz) { //子串包含参加匹配最末字符的下一节点
					//向右移动 subsz-k
					i += subsz - k;
					j = 0;
				}
				else {
					i += subsz + 1;
					j = 0;
				}
				if (i >= sz) break;
			}
			else j++;
		}
		if (j == subsz) return i;
		
	}
	return -1;
};

其它匹配算法https://www.cnblogs.com/qq78292959/p/3383953.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值