DS_字符串匹配KMP算法(个人版vs教科书版)C++实现

串的模式匹配(Pattern Matching)有一主串s1,一待匹配串t1。现在将s1的子串和t1匹配,若找到,则输出location;若没找到,则输出-1

然后,在模式匹配中(n是s1长度,m是t1长度)
(1)朴素算法就是笨方法,像我这种笨蛋想到的第一种解决方式就是它,逐一比较,复杂度是n*m
(2)有一种神奇的算法叫KMP,使得匹配速度加快(特别是n远远大于m时),降低了时间复杂度和s1长度的相关性(瞎说的,直觉是这样),因为本算法会吸取教训,让子串的匹配不重头开始逐一比较,而是退回到一定位置。

给人感觉就是,我和你长得挺像的,都是两只胳膊两条腿,比到一半发现咱们脸长的很不同,这时候,没必要把你和我的比较重新放到生物和非生物的层次来进行,而是缩小范围,放到你和我是什么灵长类范围来比较。(瞎说的,目前理解比较浅,以后想到更好的说法再修改。)

关于KMP算法的细节,此处不详细说,可以自行百度。(其实就是我现在理解比较浅,没想到通俗易懂的骚话)

接下来是算法的实现。
我在理解课本基础上写的
在这里插入图片描述

// DS_KMP_original.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include<iostream>
#include<vector>
using namespace std;

int kmp(string s1, string t1);

int main()
{
	string s1 = "ababaababac", t1 = "ababac";
	cout << "the location is " << kmp(s1, t1) << endl;
	system("pause");
    return 0;
}

int kmp(string s1, string t1)
{
	int location = -1;
	//(1).initialize the next[]
	vector<int> next;
	next.resize(t1.size());
	next[0] = -1;
	next[1] = 0;
	for (int p = 2; p <= t1.size() - 1; ++p)//next[p]
	{
		for (int i = 0; i <= p - 2; ++i)//span
		{
			bool judge = true;//the signal
			for (int j = 0, k = (p - 1) - i; j <= i; ++j, ++k)//specification
			{
				//once wrong, false
				if (t1[j] != t1[k])
				{
					judge = false;
					break;
				}
				//right till the end, true
			}

			if (judge)
				next[p] = i + 1;
		}
	}


	//(2).match the t1 in the s1 to find the location
	int j = 0;
	for (int i = 0; i <= s1.size() - 1; ++i)
	{
		//when the char is compatible
		if (t1[j] == s1[i])
		{
			//the end
			if (t1.size() - 1 == j)
			{
				location = i - (t1.size() - 1);
				break;
			}
			//not the end
			else
			{
				++j;
				continue;
			}
		}
		//when the char is not compatible
		else
		{
			j = next[j];
			if (-1 == j)
			{
				j = 0;
				continue;
			}
			else
			{
				--i;// to keep i unchanged
				continue;
			}
		}
	}
	return location;
}

时间复杂度是m的三次方+n(目前感觉是)

教科书上的设计思路
在这里插入图片描述
时间复杂度是m+n

综上所述,显然我写的比较费时。原因是在计算next[]时,也可以吸取教训,书本的:指针j在前面,指针k在后面,相同,可以赋值给++j; ++k; next[j] = k,不同,k=next[k],其实就是回溯;而我则没利用这一点。


2021.3.2补充:

关于教科书内容的理解;
1.有两个指针分别为,j和k,j在前线,k在后方;
2.当两个指针所指的字符相等,j和k分别++,并令next[j]=next[k];
3.(设主串的比较指针为i)实质上,这里可以看j指针为当前和i指针所指比较的指针,如果j所指和i所指不同,j回溯,那么回溯到哪里呢,回溯到k,为什么呢,因为我确保了[j-1]之前的串串和[k-1]之前的串串是相同的,这不正是kmp算法的精髓吗;
4.当两个指针所指的字符不同,k回溯,即k=next[k],当前的k待机,等待下次循环时比较 两个指针所指的字符,这样又回到了2和4的判断;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值