KMP算法(数据结构-字符串匹配问题)

本文介绍了KMP算法,一种用于字符串匹配的问题,对比了它与暴力算法的区别。KMP算法在匹配失败时只回溯模式串,而主串保持不动,以减少不必要的比较。文章详细解释了KMP算法的步骤,包括寻找最长前后缀,并给出了next数组的概念,帮助理解算法的工作原理。
摘要由CSDN通过智能技术生成

名词解释:

主串:比如:s1=“goodgoogle"
模式串:在主串中想要找的子串,
s2=“google”,既是在s1中找s2

普通的暴力做法:

在这里插入图片描述
有两种情况:
匹配成功:i , j都向后移动,继续比较
匹配失败:i回到最上次的下一个位置,j回到模式串的最开始
代码如下:

int find_sub_string(string s, string t)
{
   
	int i = 0, j = 0;	//初始化两个指针
    while(i<s.size() && j<t.size()){
   
        if(s[i] == t[j]){
   //sucess:
            i++;	//如果两个指针指向的字符相等
            j++;	//则将两个指针向后移动
        }
        else{
   //failure:
            i = i - j + 1;	//匹配失败,i退回到上次匹配首位,的下一位
 //j也代表着移动位置,i-j既是回到了上次的开始,+1代表下次的开始
            j = 0;			//j退回到子串首位
        }
    }
    if(j>=t.size()){
   	//j走到子串末尾说明匹配成功
        return i - j;	//匹配成功返回主串中子串出现的第一位
    }
    else 
        return -1;		//匹配失败,返回-1
}

两种算法我认为的不同之处:

暴力算法:一出错 i , j 都要回溯
KMP算法:只回溯 j,主串i 不回溯(也就是主串只向前,模式串反复横跳)

KMP算法

名词解释

字符串 abcdab
前缀的集合:{a,ab,abc,abcd,abcda}
后缀的集合:{b,ab,dab,cdab,bcdab}
那么最长相等前后缀不就是ab.

看这两个视频就够了:
基础部分【天勤考研】KMP算法易懂版

进阶部分KMP算法之求next数组代码讲解

基础

在这里插入图片描述
步骤:(看不懂不要紧)
(1)比较,直至不匹配
(2)找最长前后缀
(3) i 不动,j 回溯(如果有公共部分,保证 i 和 j 前面相同,这样可以省下部分的比较时间,没有公共前缀,j 就回到最开始 1 位置处)
(4)回到(1)

第一次:
(1)比较,直至不匹配
如图:绿色代表匹配,红色的叉代表不匹配
这个时候我们主串的i就不动了,
动模式串
在这里插入图片描述
(2)找最长前后缀
AB为最长前后缀
在这里插入图片描述
此时 i 和 j 都在6,指向不匹配的位置
(3)i 不动,j 回溯
i 不动
AB为最长前后缀,那么就让AB移动到下一个AB对齐(也就是j回退到位置3,因为公共前缀(他两个一样的)移动到了匹配的下一个
此时就是i =6 ,j = 3, i 和 j 比较
在这里插入图片描述
第二次:
(1)比较,直至不匹配
在这里插入图片描述
(2)找最长前后缀
A为最长前后缀
(3)i 不动,j 回溯
A为最长前后缀,那么就让A移动到下一个A对齐
在这里插入图片描述

第三次:
(1)比较,直至不匹配
在这里插入图片描述
(2)找最长前后缀
AB里面,没有
(3)i 不动,j 回溯
j 移动到模式串最开始处

等等…

next代码讲解

void Get_Next(char *s,int length,int *Next)
{
   
    Next[1] = 0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值