KMP-单串匹配

算法简介

这似乎是三个人提出来的一种算法,然后把三个人的名字合并在一起形成了KMP这个名字(真是诡异)。这个算法的本质是用来快速地匹配两个字符串。

暴力(n^2)

现在我们有两个字符串
s=abcabcabd
t= abcabd
求出字符串t是否是字符串s的一个子串(连续)。
我们显然可以分别枚举s匹配的起始位置,然后直接判断是否可以匹配即可。
时间复杂度 O(|s||t|) O ( | s | ∗ | t | )

KMP大法

我们可以发现在失配的时候,我们浪费了很多的时间来重新枚举,而KMP则是把这些浪费的时间全都去掉。
还是之前的两个字符串,我们匹配到第6个字符的时候发现失配了。
abcabcabd
abcabd
t串这个时候就要后移了。我们就可以用贪心的思想:t串肯定是移得越少越好嘛。
所以,我们可以定义一个next数组,next[i]表示的是:当前位置如果和第i个位置匹配,则当我们把next[i]移到到这个位置时,当前位置及前面依然是匹配的,而next[i]是整个合法方案中小于i的最大值。
所以当我们在当前位置与第i个位置失配的时候,我们就可以后移t使得next[i-1]移到当前位置的前面,接着再判断是否可以匹配,如果不行再继续,直到当前i-1没有next为止。
这样既保证了我们不会选择无用的东西,也保证了我们不会漏选有用的东西。
依然是这两个字符串,发现next[5]是2,于是我们后移
.abcabcabd
……abcabd (可能有点丑)
我们发现可以匹配了,我们就继续匹配到末尾为止。

代码(第一部分)

j=0;
for(int i=1;i<=n;i++)
{
    while(j>0&&b[j+1]!=a[i]) j=p[j];
    if(b[j+1]==a[i]) j=j+1;
    if(j==m)
    {
        j=p[j];
    }
}

此处代码是匹配多次,其中j=p[j]是每一次匹配成功后为了能够继续匹配需要将t串后移。
其中的p代表的就是next

next求法

现在的关键就是,我们怎么求next?
接着我们就可以神奇地发现,求next其实就是字符串与自己本身匹配(感受一下)。
然后,你是不是已经知道怎么做了呢?

代码(第二部分)

p[0]=p[1]=0;
int j=0;
for(int i=2;i<=m;i++)
{
    while(j>0&&b[j+1]!=b[i]) j=p[j];
    if(b[j+1]==b[i]) j=j+1;
    p[i]=j;
}

时间复杂度证明

这个算法是个二重循环,总觉得怎么都不像 O(|s|+|t|) O ( | s | + | t | )
我们来证明一下:
对于j(代码中的),每一次进入while,它都会至少减1,当它=0时,就会退出
而我们知道,j最多只会加|s|或|t|次1,因为成功匹配次数不会大于字符串长度。
所以,进入while循环的次数最多只会是|s|或|t|次。
时间复杂度就是线性的。

模板题

到哪里都可以找到吧

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值