数据结构-KMP算法

embedded/2024/9/23 6:27:20/

KMP算法

  • 简单的模式匹配算法

    • 定义:子串的定位操作通常称为串的模式匹配,他求的是子串在主串中的位置
    • 过程
      • 逐个字符比较
        1. 从主串指针 i 对应的字符和模式串指针 j 对应的字符开始,依次比较它们是否相等。
        2. 若相等,则同时移动 i 和 j 向右一位,继续比较下一个字符。
      • 失配处理
        1. 若不相等,则表明当前子串不匹配,需要根据算法类型采取不同的策略:
        2. 朴素匹配:主串指针 i 回退一位(恢复到失配前的状态),模式串指针 j 重置为起始位置,然后继续比较。
        3. 模式匹配KMP:根据预先计算的模式串的部分匹配表,将模式串指针 j 直接移动到新位置(不回溯主串),继续比较。
  • 核心思想

    • 利用已知的匹配信息

      在进行字符串匹配的过程中,当模式串与主串在某个位置发生失配时,KMP算法意识到已有的部分匹配并没有被完全浪费。这是因为,从模式串的起始位置到失配点,有一段子串已经在主串中成功匹配。这一段已匹配的子串提供了关于模式串结构的重要信息。

    • 避免回溯主串

      • 在朴素的字符串匹配算法中,一旦发生失配,需要将模式串回溯到下一个位置(通常是前一个字符),然后继续从主串的同一位置开始重新比较。这种回溯过程可能导致大量的重复比较,尤其是在模式串中有较长相同前缀的情况下
      • KMP算法的核心创新在于,它通过预先计算的“部分匹配表”(LPS表)来确定模式串失配后的下一个起始比较位置,而不需要回溯主串。部分匹配表记录了模式串中每个前缀的最长相同真前缀(同时也是后缀)的长度。当失配发生时,可以根据当前失配点对应的部分匹配表值,直接将模式串滑动到主串中相应的新位置,继续比较,而不是回溯主串。
  • 部分匹配表(LPS)

    • 最长公共前后缀:
      • 对A这个子串,前缀集合,后缀集合都为空

      • 对AB这个子串,前缀集合{A},后缀集合{B}

      • 对于ABA这个子串,前缀集合{A,AB}后缀集合{A,BA}

      • 对于ABAB这个子串,前缀集合{A,AB,ABA}后缀集合{B,AB,BAB}

      • 对于ABABC这个子串,前缀集合{A,AB,ABA,ABAB},后缀集合{C,BC,ABC,BABC}

      • 从而得到他们的next数组,部分匹配表

        ABABC
        NEXT(最长公共前后缀长度)00120
  • 代码实现

        //获取KMP算法中的next数组public static int[] kmpNext(String dest){//创建next数组int[] next=new int[dest.length()];next[0]=0;//获取next数组for (int i=1,j=0;i<dest.length();i++){while (j>0&&dest.charAt(i)!=dest.charAt(j)){j=next[j-1];}if (dest.charAt(i)==dest.charAt(j)){j++;}next[i]=j;}return next;}//j变量的作用1.追踪最长相同真前缀:初始化时,j 被设置为 0,表示当前正在考虑的最长相同真前缀起始于模式串的第一个字符。在外层 for 循环中,随着 i 从 1 到 dest.length()-1 递增,j 用于追踪模式串中以第 i 个字符结尾的子串的最长相同真前缀的最后一个字符的索引。2.更新最长相同真前缀:当 dest.charAt(i) 与 dest.charAt(j) 相等时,说明当前字符可以延长最长相同真前缀,因此将 j 增加 1,继续追踪更长的相同真前缀。将 j 设置为 next[j-1],意味着将当前考虑的最长相同真前缀的起始位置回溯到这个较短的相同真前缀的起始位置。这样做可以避免重新检查那些已经确认匹配的字符,因为它们构成了相同的真前缀。
    
        /**** @param str1 模式串* @param str2 子串* @param next next数组* @return 若没找到返回-1,找到就返回在模式串中的下标*/public static int kmpSearch(String str1,String str2,int[] next){for (int i=0,j=0;i<str1.length();i++){while ((str1.charAt(i)!=str2.charAt(j))&&j>0){//通过next数组找到前一个位置子串的最长公共前后缀的索引值j=next[j-1];}if (str1.charAt(i)==str2.charAt(j)){j++;//子串索引后移}if (j==str2.length()){return i-j+1;}}return -1;}
    

http://www.ppmy.cn/embedded/7274.html

相关文章

Springboot集成Ehcache3实现本地缓存

如果只需要在单个应用程序中使用本地缓存&#xff0c;则可以选择Ehcache&#xff1b;它支持内存和磁盘存储&#xff0c;这里不以注解方式演示&#xff0c;通过自己实现缓存管理者灵活控制缓存的读写&#xff1b; 1、引入相关依赖 <!-- ehcache3集成start --><depende…

软件测试的经验和教训

1. 认知心理学是测试的基础。 >>>对事物的认知程度&#xff0c;才能对事物做出评价。对事物没有任何认知和了解&#xff0c;就不会有判断<<< 2. 与测试有关的一些问题&#xff1a; a.人的感觉和记忆可靠性 b.信念从哪里来 c.信念如何影响人的行为 d.做…

封装原生html的table处理方法【参数类似eltable】

直接跑html即可 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>封装原生talbe</title> </…

【贪玩巴斯】Vm/ubantu虚拟机报错04005和70057解决方法如下(基于WindowsX64系统)

&#x1f4da;Vm/ubantu虚拟机报错04005和70057解决方法如下&#xff08;基于WindowsX64系统&#xff09;&#xff1a; 错误1场景描述&#xff1a;04005 返回 代码:E_FAIL (0X80004005)组件:SessionMachine界面:ISession {c0447716-ff5a-4795-b57a-ecd5fffa18a4}打开电脑启动虚…

mapreduce中的ReduceTask工作机制(Hadoop)

ReduceTask 是 Hadoop 中的一个重要组件&#xff0c;负责对 MapTask 的输出进行合并、排序和归并&#xff0c;最终生成最终的输出结果。 ReduceTask 的工作机制 1. 分组&#xff08;Shuffle&#xff09;阶段&#xff1a; 在分组阶段&#xff0c;ReduceTask 会从多个 Mapper …

Spark---核心概念(Spark,RDD,Spark的核心构成组件)详解

一、什么是Spark Spark就是一个集成离线计算&#xff0c;实时计算&#xff0c;SQL查询&#xff0c;机器学习&#xff0c;图计算为一体的通用的计算框架。 二、Spark特点 1、速度快 相比较于MR&#xff0c;官方说&#xff0c;基于内存计算spark要快mr100倍&#xff0c;基于磁…

在线拍卖系统,基于SpringBoot+Vue+MySql开发的在线拍卖系统设计和实现

目录 一. 系统介绍 二. 功能模块 2.1. 管理员功能模块 2.2. 用户功能模块 2.3. 前台首页功能模块 2.4. 部分代码实现 一. 系统介绍 随着社会的发展&#xff0c;社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系…

centos 6设置yum源遇到的问题

由于centos6已经不被支持了&#xff0c;直接抄人家的命令是不行的 比如执行这些&#xff08;是wget或者是curl按照自己的改&#xff09; wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-6.repo yum makecache会报错 需要到对应的镜像源网…