KMP算法【查找字符串中子串位置】

KMP算法

作用

KMP算法的作用是查找子串在母串中的位置
比如查找“gle”在“googlegoo”中位置
算法的时间复杂度为:O(n)
算法的空间复杂度为:O(n)

思想

对下面的情况,传统方法从target的第一位和母串的第2位重新开始匹配,而KMP算法仅需从母串的第第4位和target的第3位继续进行匹配,这是因为已排序target部分是“111”,最大前后缀相同的部分是“11”所以可以直接完成跳跃。
在这里插入图片描述
那么问题就转变为了如何求已匹配部分的最大相同前后缀的长度。

已匹配部分最大相同前后缀的长度求解过程(dp)

匹配过程中会产生大量的已匹配子串,对应需要进行大量最大相同前后缀长度的计算,考虑到这些直接进行动态规划提前求取在target各个位置完成匹配时对应的最大相同前后缀的长度。

下面是kmp求解过程:
在这里插入图片描述
变量含义:j匹配字符个数,i当前待匹配索引
关键节点解析:

  1. target[i]!=target[j],nums[i]=0;
  2. target[i]==target[j],j++,nums[i]=1,进入下一轮比较
  3. target[i]!=target[j],此时是否类似于从11中找12,根据已匹配字符串j直接跳跃到nums[j-1],再判断发现相等,j++,nums[i]=1
  4. target[i]==target[j],j++,nums[i]=2
  5. target[i]==target[j],j++,nums[i]=3
  6. target[i]!=target[j],进行跳跃,已匹配子串是123,跳跃到nums[j-1]即j=2,继续比较发现还不相等,再进行跳跃,跳到nums[j-1]即j=1,还不相等继续跳,跳到j=0没得跳了,一比较发现不相等,nums[i]=0

代码实现

通过上边的推到我们发现实际上求解dp数组的过程和匹配字符串的过程是相同的因而照抄即可,在j==target.size()位置输出即可

void init(vector<int>&nums,string& t){
	for(int i=1,j=0;i<t.size();i++){
		while(j&&nums[i]!=nums[j]){
			j=nums[j-1];
		}
		if(nums[i]==nums[j]) j++;
		nums[i]=j;
	}
}
int find(string s,string t){
	if(t.empty()) return -1;
	vector<int>tmp(t.size(),0);
	init(tmp,t);
	for(int i=0,j=0;i<s.size();i++){
		while(j&&s[i]!=t[j]){
			j=tmp[j-1];
		}
		if(s[i]==t[j]) j++;
		if(j==t.size()) return i-t.size()+1;
	}
	return -1;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值