字符串匹配问题(KMP)

news2024/11/30 10:27:57

文章目录

    • 题目
    • KMP 算法
      • 1)例子演示
      • 2)KMP算法思路
      • 3)疑惑模型验证
      • 4)求 next 数组
      • 5)代码演示
      • 6)复杂度分析

题目

有字符串 str1 和 str2 ,str1 中是否包含 str2,如果没有包含返回 -1,如果包含,则返回 str2 在 str1 中开始的位置

注:保证 str1 和 str2 字符串的长度大于 0,str1 长度为N,str2 长度为 M

之前有介绍过如果使用 BF 算法和 RK 算法来解决字符串匹配问题,但是两者都会有缺点,或是效率低下,或是性能不稳定,KMP 算法可以解决这样的问题,以一种非常巧妙的思路解决问题

链接直达——》字符串匹配算法 (BF & RK)

KMP 算法

1)例子演示

str1 和 str2 如图所示,准备变量 x、y,依次进行匹配,如果相同,x 和 y 共同向后移动一格

此时,str1 的 x 位置和 str2 的 y 位置的字符出现了不同,此时我将前面的 “ababa” 字符视作已匹配前缀,在下一轮中我们将移动 y,继续进行匹配

在这里插入图片描述

我们需要在已匹配前缀(“ababa”)中找到最长前缀(后缀)可匹配子串,即 “aba”,长度为 3

(注:最长前缀(后缀)可匹配子串不可以是已匹配前缀字符串本身)

在这里插入图片描述

在这一轮中,将 y 移动到 str2 的 3 下标上,x 位置和 y 位置的字符继续进行比较

在这里插入图片描述

发现 x 位置和 y 位置上的字符仍然不一样,这个时候的已匹配前缀为 “aba”,该字符串的最长前缀(后缀)可匹配子串是 “a”,长度为 1

在这里插入图片描述

在这一轮中,将 y 移动到 str2 的 1 下标上,x 位置和 y 位置的字符继续进行比较

在这里插入图片描述

发现 x 位置和 y 位置上的字符仍然不一样,这个时候的已匹配前缀为 “a”,该字符串的最长前缀(后缀)可匹配子串不存在了,长度为 0,那么将 y 移动到 str2 的 0 下标上,x 位置和 y 位置的字符继续进行比较

在这里插入图片描述

发现 x 位置和 y 位置上的字符仍然不一样,此时 y 已经没有办法再后退了,x 位置及其之前的字符都不可能成为成功匹配 str2 的首字符,x 向后移动一格

在这里插入图片描述

发现 x 位置和 y 位置上的字符终于一样了,x 和 y 一起向后移动一格,再比较字符,依次类推,直到 x 和 y 有一个等于对应的字符串的长度,就不再结束匹配操作。

如果此时 y 等于 str2 的长度,说明匹配成功了,返回 x - y,反之失败,返回 -1

在这里插入图片描述

2)KMP算法思路

  • x、y 分别从 str1、str2 的 0 坐标出发,每次比较 x 位置的字符和 y 位置的字符
  • x、y 位置的字符相同,就共同向后移动一格;
  • 不同就根据已匹配前缀的最长前缀(后缀)可匹配子串的长度(len),将 y 移动到 str2 的 len 下标处;
  • y 已经在下标 0 处,就把 x 向后移动一格
  • 直到 x 或 y 越界。y 越界,匹配成功,反之,匹配失败

3)疑惑模型验证

提问1:

为什么在 y 位置和 x 位置的字符不同时,可以根据最长前缀(后缀)可匹配子串的长度将 y 直接移动?(假设 str1 从位置 i 到 位置 x-1这段字符串和 str2 从位置 0 到位置 y-1这段字符串是能够匹配成功的)

答1:

在这里插入图片描述

假设此时 ① 区域是最长前缀可匹配子串,② 区域是最长后缀可匹配子串,两区域字符串一定相等。

根据题意,亦可得 ③ 区域和 ② 区域是相等的,根据传递性, ① 区域的字符串等于 ③ 区域的字符串,y 可以直接移动到 ① 区域后面一个字符的位置,下一轮依旧比较 x 位置和 y 位置的字符

提问2:

为什么能够这么自信的跳过 i + 1 位置到 j - 1 位置的子符,坚信他们中不会有字符成为匹配成功 str2 的首字符?

答2:

在这里插入图片描述

首先明确好① 区域是最长前缀可匹配子串,② 区域是最长后缀可匹配子串

假设 str1 字符串中 i + 1 位置到 j - 1 位置中有 R 位置,R 位置就是能够成功匹配 str2 的首字符位置

在这里插入图片描述

那么因为直到 x 位置和 y 位置开始才有字符出现不同,那么 ④ 区域和 ③ 区域一定相同

R 是首字符位置,R 位置的字符一定等于 str2 中 0 下标的字符,不管怎么样 ⑤ 区域一定等于 ③区域,根据传递性, ④ 区域和 ⑤ 区域一定相同,和原本指定好的最长前缀(后缀)可匹配子串长度不同了,自相矛盾,假设不成立

4)求 next 数组

next 数组实际上就是一个一维数组,长度为 str2 字符串的长度,下标和 str2 字符串的下标是一一对应的,代表着对应子符的已匹配前缀的最长前缀(后缀)可匹配子串的长度

在这里插入图片描述

注:无前缀的情况,规定 next 对应的下标的值为 -1

那么如何求得 next 数组呢?如果每次求最长前缀(后缀)可匹配子串的长度时都要依次把已匹配前缀的的每一种情况进行比较尝试的话,效率显而易见的低

可以使用动态规划,动态规划就是大事化小的分治思想,我们有明确的信息 next[0] = -1,next[1] = 0,没有办法下一子根据这两个信息获得 next[i] 的值,但是我们可以 next[1] 的值求得 next[2] 的值,只要把处理好的结果进行保存,那么在处理更大规模问题(求 next[i])时就可以使用这些结果

举例:

我们现在要求得 next[i] ,next[x](0 <= x <= i-1)的值是我们已经求得知晓的

在这里插入图片描述

已知 next[i-1] = 4,使用一个变量 j 指向 str2 的 j 下标上。

此时这个 j 有两层含义:

① next[i-1]的值

② 哪个位置的字符和 i-1 位置上的字符进行对比

没错,我们就要拿 j 位置的字符和 i-1 位置上的字符进行对比,从而尝试求得 next[i] 的值

下图所示,j 位置的字符和 i-1 位置的字符是一样的,那么 next[i] = ++j = 5

注:++j 实际上是两个步骤:① j 自增一变成 5 ② 求得 next[i] 的值是 5

在这里插入图片描述

如果 j 位置的字符和 i-1 位置的字符不同,"abab"这个最长前缀可匹配子串没法完整用上了,只能退而求其次,让 j 回退到 next[j] 处

再次比对,发现此时 j 位置的字符和 i-1 位置的字符是一样的,那么 next[i] = ++j = 3

在这里插入图片描述

假设发现 j 位置的字符和 i-1 位置的字符不同,那就一直遵循上面的思想,一直回退,直到 j = 0,退不了了,next[i] 的值就是 0

5)代码演示

public static int KMP(String str1,String str2) {
    char[] chs1 = str1.toCharArray();  //变成字符数组
    char[] chs2 = str2.toCharArray();
    int[] next = getNextArray(chs2);   //获取到 next 数组数据
    int x = 0,y = 0;
    //循环条件就是 x 和 y 都不可以越界
    while (x < str1.length() && y < str2.length()) {
        if (chs1[x] == chs2[y]) {
            x ++;  //相同一起走
            y ++;
        } else if (y > 0) {
            y = next[y];  //不同,但是 y > 0,y 回退
        } else {
            x ++;  //不同,并且 y == 0,无路可退,x 后移一格
        }
    }
    return y == str2.length() ? x-y : -1;  //y 越界匹配成功,反之失败
}

public static int[] getNextArray (char[] chs) {
    int[] next = new int[chs.length];
    next[0] = -1;
    next[1] = 0;    //初始值
    int j = 0;//表示 next[i-1],回头需要和 i-1 位置上的字符进行比对
    int i = 2;
    while (i < next.length) {
        if (chs[i-1] == chs[j]) {
            next[i++] = ++j; //相同,next[i]=j+1,i++,j++
        } else if (j > 0) {
            j = next[j];     //不同,退而求其次,回退
        } else {
            next[i++] = 0;   //不同,无路可退,next[i]=0,i++
        }
    }
    return next;
}

6)复杂度分析

空间复杂度:

开辟的额外空间只有 next 数组,由于 str2 的长度为 M,所以空间复杂度就是 O(M)

时间复杂度:

首先分析匹配过程(KMP 方法),在整个匹配过程中,str1 中的 x 变量是不会回退的(str1 不动),而 str2 中的 y 变量在匹配失败时是会向左回退的(相当于将 str2 向右推),直到在滑动的过程中匹配成功,循环结束,或者滑到最右,仍然匹配失败,循环结束

滑动长度为最大为 N,时间复杂度为 O(N)

在求 next 数组时,时间复杂度为 O(M)

所以总的时间复杂度O(N+M)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/84846.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

电商行业用天翎低代码平台做客服管理系统

编者按&#xff1a;在市场竞争越来越激烈的今天&#xff0c;客服作为电商行业的重要组成部分&#xff0c;如何科学管理成为企业管理层不可避免的难题&#xff0c;做好客服管理对企业具有重要意义。本文通过唯品会金牌客服管理系统案例介绍了低代码平台在定制化和快速落地的特点…

python tkinter 登录 计算器

使用tkinter开发图形化小项目&#xff1a; 功能&#xff1a; 登录 &#xff1a;登录成功 跳转到 计算器 页面&#xff0c;否则登录失败计算器 &#xff1a;登录成功后&#xff0c;窗口标题栏显示当前登录的用户 技术&#xff1a; 面向对象标准模块SQLite数据库登录成功后页…

SpringCloud MQ介绍与使用

哈喽~大家好&#xff0c;这篇来看看SpringCloud MQ介绍与使用。 &#x1f947;个人主页&#xff1a;个人主页​​​​​ &#x1f948; 系列专栏&#xff1a;【微服务】 &#x1f949;与这篇相关的文章&#xff1a; SpringCloud Sentinel 使用…

基于Python+Django的银行取号排队系统 毕业设计

随着信息技术和网络技术的飞速发展&#xff0c;人类已进入全新信息化时代&#xff0c;传统管理技术已无法高效&#xff0c;便捷地管理信息。为了迎合时代需求&#xff0c;优化管理效率&#xff0c;各种各样的管理系统应运而生&#xff0c;各行各业相继进入信息管理时代&#xf…

clickhouse集群搭建、SpringBoot集成及应用

前言 在日常工作中&#xff0c;日志查询是我们不可避免的业务场景&#xff0c;当项目访问量较小时&#xff0c;我们可以将日志存储在MySQL或其他行式数据库中&#xff0c;但是如果项目访问量很大&#xff0c;一次查询就会给数据库带来很大压力&#xff0c;也许你会采用elk等成…

测试框架Pytest-pytest测试用例的运行实操

一、单元测试框架 1、什么是单元测试框架 单元测试是指在软件开发当中&#xff0c;针对软件的最小单位&#xff08;函数、方法&#xff09;进行正确性的检查测试。 2、单元测试框架 java&#xff1a;junit和testing python:unittest和pytest 3、单元测试框架主要做什么&a…

基于JSON的SQL注入攻击触发需要更新Web应用程序防火墙

©网络研究院 安全研究人员开发了一种通用的 SQL 注入技术&#xff0c;可以绕过多个 Web 应用程序防火墙 (WAF)。问题的核心是 WAF 供应商未能在 SQL 语句中添加对 JSON 的支持&#xff0c;从而使潜在的攻击者可以轻松隐藏其恶意负载。 Claroty Team82 的研究人员发现的绕…

绿盟SecXOps安全智能分析技术白皮书 思路方案

安全数据资产 统一管理DataOps&#xff0c;即 Data 和 Operations 的集成&#xff0c;于 2014 年首次提出。Gartner 将 DataOps 定义为“一种协作性的数据管理 实践&#xff0c;专注于改进组织内数据管道的通信、集成和自动化”[7]。DataOps 是一种面向流程的自动化方法&#x…

【C++笔试强训】第六天

文章目录选择题编程题选择题 1.十进制变量i的值为100&#xff0c;那么八进制的变量i的值为&#xff08;&#xff09; A 146 B 148 C 144 D 142 进制之间的转化&#xff0c;这不用多说了把 2.执行下面语句后的输出为 int I1; if(I<0)printf("****\n") ; els…

大数据Kudu(四):Kudu集群搭建

文章目录 Kudu集群搭建 一、kudu 安装包 二、节点规划及安装 1、首先在每个节点上传安装包 2、在node1、node2节点上安装如下rpm安装包 3、在node3节点上安装如下rpm安装包 4、配置Master Server 5、配置Tablet Server 6、Master节点配置所有Master Server 7、Server…

对DataFrame中元素进行定位并修改的DataFrame.iat[]方法

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 根据指定的行和列的位置号 显示或修改DataFrame中相应位置的元素 DataFrame.iat[x,y] 选择题 关于以下python代码说法错误的一项是? import pandas as pd df pd.DataFrame({"A"…

手把手教你搭建自己的FTP文件服务器

大家好&#xff0c;我是小豪&#xff0c;今天我来给大家分享如何在虚拟机上搭建自己的文件服务器 文章目录Linux上安装文件服务器FTP安装VSFTP下载dnf下载VSFTP清除防火墙的iptables缓存下载FTP匿名访问模式本地用户模式Linux上安装文件服务器FTP 由于FTP、HTTP、Telnet等协议…

【阿里实践】基于深度学习的个性化推荐系统实时化改造与升级

省时查报告-专业、及时、全面的行研报告库省时查方案-专业、及时、全面的营销策划方案库【免费下载】2022年11月份热门报告盘点推荐技术在vivo互联网商业化业务中的实践.pdf推荐系统基本问题及系统优化路径.pdf大规模推荐类深度学习系统的设计实践.pdf荣耀推荐算法架构演进实践…

doom emacs如何安装新插件和自定义快捷键

doom emacs如何安装新插件和自定义快捷键 最近在学习和使用doom emacs&#xff0c;遇到了2个问题。 问题1: 虽然doom emacs已经配置了很多的三方插件&#xff0c;但是还有些个性化的插件如何按doom风格添加&#xff1f; 问题2: 有些快捷键自己已经熟悉&#xff0c;如何修改&am…

双目密集匹配及SGM算法

提示&#xff1a; 双目密集匹配及SGM算法前言一、双目密集匹配1、双目密集匹配概述2.、双目密集匹配四大步骤代价计算&#xff08;per-pixel-cost&#xff09;&#xff1a;释义&#xff1a;代价聚集&#xff08;cost-aggregation&#xff09;:释义&#xff1a;分类&#xff1a;…

以就业为目标,Python到底应该学什么?

前言 很多小伙伴知道Python火爆薪资高&#xff0c;开始自学&#xff0c;可是并不知道Python应该学哪些技术、学到什么程度才能找到工作。今天我们就来分析一下&#xff0c;Python学到什么程度才能找到工作。 相关&#xff1a;我是今年刚刚毕业的不入流大学的本科生&#xff0…

KingbaseES Create Index Concurrently 过程探究

前言&#xff1a; 我们知道Oracle 可以通过create index online 在线创建索引&#xff0c;而不影响其他会话修改数据&#xff0c;但Oracle 实际在online 创建索引的最后一步&#xff0c;实际还是需要进行锁升级&#xff0c;申请表级的S锁&#xff0c;因此&#xff0c;最后还是有…

STM32CUBEMX开发GD32F303(17)----内部Flash读写

概述 本章STM32CUBEMX配置STM32F103&#xff0c;并且在GD32F303中进行开发&#xff0c;同时通过开发板内进行验证。 本例程主要讲解如何对芯片自带Flash进行读写&#xff0c;用芯片内部Flash可以对一些需要断电保存的数据进行保存&#xff0c;无需加外部得存储芯片&#xff0c…

广告公司到底干什么的?欣奥诚分享

广告公司到底干什么的&#xff1f; 这篇文章从产业的角度拆分广告业&#xff0c;还原一个真实的广告业出来。 01. 它们是谁&#xff1f; 早年广告业有4类公司&#xff1a;品牌咨询类公司&#xff1b;设计创意类公司&#xff1b;媒介投放类公司&#xff1b;活动执行类公司。 …

[附源码]Python计算机毕业设计电子病历系统Django(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等…