首页 > 编程语言 >KMP算法笔记

KMP算法笔记

时间:2023-07-19 18:11:47浏览次数:51  
标签:字符 匹配 前缀 后缀 needle 笔记 next 算法 KMP

1.概念解析

 前置:

  将原串称之为 文本串,匹配串称之为 模式串。

  KMP的实质其实就是:利用已经匹配的信息,来加速查找的过程。

  对于暴力解法而言,当我进行模式串匹配时,遇到一个不匹配的字符,那么只能一步一步往下滑动,然后重新匹配。

  但是对于KMP算法而言,利用到了 前缀子串后缀子串的匹配信息。

 什么是前缀子串和后缀子串:

  以字符串 abc 为例:{ 'ab' , 'a' } 就是它的前缀集合,{ 'bc' , 'c' } 就是它的一个后缀集合;

  But,注意了'abc'本身不算在前后缀里

  定义:

  •   前缀是指不包含最后一个字符的所有以第一个字符开头的连续子串。
  •   后缀是指不包含第一个字符的所有以最后一个字符结尾的连续子串。

  那么对于KMP算法而言就是要用到 模式串最长公共前后缀 来加快模式匹配

  注意黑体,是模式串的最长前后缀,那么这个最长公共前后缀的求取是和文本串没有关系的

  那么我们只需要利用一个前缀表next来存储每个位置的最长公共前后缀即可,例如对于字符串 "abababca"

  注:pmt是原始的前缀表,next是减1后的前缀表;二者原理一样,只是实现代码的方式略有区别罢了

  这里解释用pmt解释(易懂一些),代码实现采用了next(减1法)

   那么例如对于 index=0 而言,a是首位,没有前后缀,那么就是 0,index=2 而言呢,前后各一个 'a' ,故最长公共前后缀为1.以此类推

2.代码实现

  这里采用减一法来实现:

  

class Solution {
public:
    void getPreArray(int* next, string& needle)
    {
        int j = -1;   //j<0其实本质对应了没有匹配的前后缀
        next[0] = -1;
        for (int i = 1; i < needle.size(); ++i)
        {
            //这里为什么j>=0 ? 因为j>=0表明了i前面一个字符至少有一个匹配的
            //否则 i-1 的位置和第一个字符都不匹配,直接拿 i 位置和第一个字符比较即可
            while (j >= 0 && needle[i] != needle[j + 1])
                j = next[j];
            //当needle[i] != needle[j + 1]时呢,我们就要利用前缀表移动位置了!
            //j=next[j] 其实就是移动到公共前后缀的下一位
            //为什么要用while循环呢? 因为这个位置的公共前后缀下一位不一定匹配呀!我们要求匹配的前缀表
            
            //如果等于,就说明有字符匹配了,那么说明至少匹配一个字符(例如头部),j++咯
            if (needle[i] == needle[j + 1]) 
                
                j++;
            next[i] = j;
        }
    }
    int strStr(string haystack, string needle) {
        int j = -1;
        int* next = new int[needle.size()];
        getPreArray(next, needle);
        for (int i = 0; i < haystack.size(); ++i)
        {
            while (j >= 0 && haystack[i] != needle[j + 1])
                j = next[j];
            if (haystack[i] == needle[j + 1])
                ++j;
            if (j == (needle.size() - 1))
                return i;
        }
        return -1;
    }
};

 

3.反思

  博主其实理解了蛮久了,可能讲述的不会很好(主要为自己疑惑的点做个笔记,后续想到更好的表达会更新),推荐下面一个链接理解:

  (53 封私信 / 17 条消息) 如何更好地理解和掌握 KMP 算法? - 知乎 (zhihu.com)

 

  

  

 

标签:字符,匹配,前缀,后缀,needle,笔记,next,算法,KMP
From: https://www.cnblogs.com/Kellen-Gram/p/17566282.html

相关文章

  • 最短路之dijkstra算法
    dijkstra比之上次介绍的的bellman-ford算法的用途上最大的区别就是dijkstra只可用于求无负权边图中的最短路,堆优化后的dij比bellman-ford的复杂度(mn)更小(mlogn)代码源关于dijkstra的解释简单来讲就是每次选出一个没被选过的离起点最近的点,松弛这个点所在的每个边,直到所有点都被......
  • 最短路之 Bellman-ford 算法
    bellman-ford算法的思想:若有向图有n个点,m条边。扫描所有边,对每条边进行一次松弛(即对a,b为端点,权重为w的边,dist[b]=min(dist[a],dist[a]+w))重复此流程(最多重复n次)直到没有更新操作发生例题1bellmanford板子给你一张n个顶点m条边的有向简单图,顶点编号从1到......
  • Web前端学习笔记
    <!DOCTYPEhtml><htmllang="en"><head>  <metacharset="UTF-8">  <metaname="viewport"content="width=device-width,initial-scale=1.0">  <title>welcometomyworld</ti......
  • FreeType 控制台渲染字形轮廓笔记
    项目里用到了FreeType解析字体,这里只为了更方便入手FreeType,简单读取字体文件,并在控制台绘制制定字符轮廓,以字符A为例:初始化FreeType,加载字体文件#include<freetype2/ft2build.h>#includeFT_FREETYPE_H#include<iostream>#include<math.h>usingnamespacestd;......
  • 历年检测、分割、生成算法梳理(2023)
    检测算法 分割算法 生成算法 ......
  • 雷达算法 | 一种适用于汽车雷达的聚类算法研究与分析
    公众号【调皮连续波】,其他平台为自动同步,同步内容若有不全或乱码,请前往公众号阅读。保持关注调皮哥,获得更多雷达干货学习资料和建议,助力大家轻松、快乐、有方向地学习雷达技术。本文参考TI的一种适用于汽车雷达的聚类算法研究和实现.pdf文档由于不涉及硬件,因此本文仅对算法部分进行......
  • 校招 | 2023届应届生毫米波雷达算法岗秋招经历分享
    本文首发于公众号【调皮连续波】,其他平台为自动同步,同步内容若有不全或乱码,请前往公众号阅读。保持关注调皮哥,获得更多雷达干货学习资料和建议,助力大家轻松、快乐、有方向地学习雷达技术。知乎:https://zhuanlan.zhihu.com/p/576656211。原创作者: @探索Seeker本文经过原创作者同意,......
  • Learning hard C#学习笔记——读书笔记 07
    1.值类型和引用类型1.1什么是值类型和引用类型值类型:包括简单类型,枚举类型,结构体类型等,值类型通常被分配在线程的堆栈上,变量保存的内容就是实例数据本身引用类型:引用类型实例则被分配在托管堆上,变量保存的是实例数据的内存地址,引用类型主要包括类类型、接口类型、委托类型......
  • java parallelStream 线程堵塞问题笔记
    定义:Stream(流)是JDK8中引入的一种类似与迭代器(Iterator)的单向迭代访问数据的工具。ParallelStream则是并行的流,它通过Fork/Join框架(JSR166y)来拆分任务,加速流的处理过程。最开始接触parallelStream很容易把其当做一个普通的线程池使用,因此也出现了上面提到的开始的时候打标,结束......
  • c++笔记-scoped_lock/unique_lock解析
    目录scoped_lockvsunique_lock灵活性生命周期资源所有权性能对比例源码unque_lockscoped_lockscoped_lockvsunique_lock在C++中,std::scoped_lock和std::unique_lock都是用来管理互斥量(mutex)的RAII(ResourceAcquisitionIsInitialization)类,用于简化多线程编程中的锁管理。它......