KMP算法(思想真的不复杂)

2023-10-31

在了解KMP之前,我们需要了解两个概念,字符串的前缀,和字符串的后缀

字符串的前缀,我举个例子你们就懂了,一个字符串abcde,它包含的前缀有,{a, ab, abc, abcd}
字符串的后缀,{bcde, cde, de, e}
知道这两个概念后,我们就可以来聊kmp的思想了,现在假如我们需要知道一个字符串(这个字符串我们称为被匹配字符串)中是否包含另一个字符串(这个字符串我们称为被目标字符串),我们最容易想到的自然就是遍历匹配字符串中每一个字符为开头,然后逐一向下匹配。这样自然是可以也很容易想到,但是我们能不能投个懒,比如我们目标字符串根匹配字符串匹配到了4个字母,abab,然后下一个字母匹配失败了,按我们之前的想法,我们肯定是从目标字符串的b开始匹配了。这时候我们仔细观察下这个匹配成功的字符串,你会发现,前面有一个ab后面有一个ab,这时候我们的匹配字符串根本不用从头开始匹配了,直接跳到ab开始,然后接着匹配下一个。

Alt text

我们注意i和j的位置,上面一个就是匹配字符串,下面是目标字符串,按我们之前的暴力破解,如果i和j这时候没有匹配成功,i是要到b的位置,j是要从头开始的,我们观察结构可以发现根本不用这样,匹配到的有重复的子结构,我们i根本不用动,j的位置移到第二个ab的a处重新匹配就好了
根据上面讲的,如果我们把目标字符串,从头开始依次增加的子串建立一个前缀和后缀的最大匹配表,那么我们每次匹配成功的字符串,我们就可以知道它的前缀和后缀匹配的最大长度。依照图片上,我们i就可以不用动了,j移到对应的最大长度的下一个位置就可以接着匹配了。最关键的就是如何建立起这个最大匹配表,下面的代码就是如何建立最大匹配表(这个表我喜欢这么叫,它原来是叫部分字符匹配表,PMT)。
public static int[] getMatchTable(string str) {
	//用来存放最大的前后缀匹配长度,比如上面的abab它的最大匹配长度是2,它的长度是4,所以索引3处是2,后面依次类推
	int [] matchTable = new int(str.length());
	for(int i = 0, int j = 1; j < matchTable.length; j++) {
		//这是建立这个表最关键的地方,如果之前匹配成功了,这次没有匹配成功
		while(i > 0 && str.charAt(i) != str.charAt(j)) {
			//这里我们其实也是字符串匹配,我们可以使用前面的部分字符匹配表
			i = matchTable[i - 1];
		}
		//成功把前缀对应索引加一,索引的位置也就是匹配的数量
		if(str.charAt(i) == str.charAt(j)) {
			i++;
		}
		//把对应字符位置的最大匹配数量设置进去
		match[j] = i;
	}
	return match;
}
部分字符匹配表一出来,按照我们上面的思路,两个字符串匹配就可以省去很大的功夫了
//str为被匹配字符串
//target为目标字符串
//找了返回匹配到的开始位置,没有匹配到返回-1
private static int match(int[] matchTable, String str, String target) {
        //被匹配串索引
        int i = 0;
        //目标字符串索引
        int j = 0;
        for (; i < str.length(); i++) {
        	//没有匹配到,如果之前有匹配到,我们就需要在表里去找最大的前后缀匹配长度了
            while (j > 0 && target.charAt(j) == str.charAt(i)) {
                j = matchTable[j - 1];
            }
            
            //匹配到了接着匹配下一个
            if (target.charAt(j) == str.charAt(i)) {
                j++;
            }
            
            if (j == target.length()) {
                return i - j + 1;
            }
        }
        return -1;
    }
到此KMP算法计算结束了,还没理解的话,可以照着代码dug琢磨几遍,代码纯手打,也是为了巩固自己的记忆,如有错误遗漏之处,也请指出。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

KMP算法(思想真的不复杂) 的相关文章

随机推荐

  • TrainingOperator--PyTorchJob实现机制分析

    前言 由 Pytorch分布式训练 一 chenxy02的博客 CSDN博客 可知Pytorch分布式训练实现进程间寻址 主要依靠以下 四个参数 MASTER ADDR MASTER PORT WORLD SIZE RANK MASTER
  • ardupilot开发 --- 避障篇

    避障的类型 空中防碰撞ADSB 主要是防止与其他飞行器的碰撞 避障 防止与天花板地板障碍物的碰撞 实现避障必要的传感器 ADSB receivers Rangefinders or Proximity Sensors or Realsens
  • 给你一个字符串 s,由若干单词组成,单词前后用一些空格字符隔开。返回字符串中最后一个单词的长度。

    提示 题目答案均由博主自主编写 想法不一 答案也不一 本答案仅提供参考 如有疑问 可在评论区提问 有时间会解答 题目描述 给你一个字符串 s 由若干单词组成 单词前后用一些空格字符隔开 返回字符串中最后一个单词的长度 单词是指仅由字母组成
  • 用python语言判断素数(质数)

    今天查了很多关于判断质数的代码 自己也尝试写了一下 质数是指在大于1的自然数中 除了1和它本身以外不再有其他因数的自然数 所有我们能很容易的想到使用for循环来实现输入数m和 2 m 1 的相除 代码实现 m eval input 请输入一
  • web服务器接口文档,接口文档

    有字库接口文档 由于中文字体文件过大 有字库采用 按需截取 根据页面内容把字体中不需要的字型删除掉 的方案 将中文字体压缩成和英文字体一样小巧玲珑 按需截取 与 整套嵌入 方案相比 1 按需截取 生成的中文字体只有十几K至一百多K 而 整套
  • 关于测试的静态方法学习笔记

    在学习软件测试时的一些笔记 可以加深对测试的理解 静态测试技术概述 1 静态测试是不执行被分析的程序 而是通过对模块源代码进行研读 找出其中的错误或可疑之处 收集一些度量数据 2 静态测试包括对软件产品的需求和设计规格说明书的评审 对程序代
  • docker安装wordpress

    参考文章 步骤 1 安装docker 2 下载wordpress镜像 3 下载mysql镜像 4 启动mysql容器 5 启动wordpress容器 遇到的问题 1 进入wordpress报数据库错误 猜测是连不上数据库 在宿主机尝试连接M
  • Qt on Android 之设置应用名为中文

    今早群里有个盆友问如何将 Qt 开发的 Android 应用的名字设置为中文 试验了一下 有两个办法 直接修改 AndroidManifest xml 文件 首先你在创建 Qt on Android 工程时需要创建一个 AndroidMan
  • Gmail,Qmail,163等邮件服务器SMTP、IMAP、POP3、地址及SSL/非SSL协议端口号

    最近项目需要给后台发送邮件 将项目中部分信息与后台同步 于是就有了这篇博客 以下的内容是参考网上的例子加上自己实践总结了一下 邮箱默认配置 服务器名称 服务器地址 SSL协议端口号 非SSL协议端口号 IMAP imap xx com 99
  • WebService客户端几种实现方式

    文章目录 一 发布一个webservice服务 jdk原生 1 编写服务接口 2 服务实现类 3 发布服务 4 浏览器查看是否发布成功 二 几种客户端调用方式 1 jdk原生调用 需要获取服务接口文件 2 用import命令生成客户端代码
  • idea远程断点调试

    在idea里面配置远程断点调试 192 168 198 130 是远程服务端口 5005是远程服务连接端口 在linux启动在线服务 在启动服务里面加入参数 Xdebug agentlib jdwp transport dt socket
  • ArtPi 认识RTT Studio建立LED工程

    1 认识RTT Studio建立LED工程 软件IDE RT Thread Studio 版本 2 1 1 硬件平台 ART Pi CPU STM32H750XB 开发板基本外设功能实现 串口 uart4 PA0 PI9 Red LED P
  • vmware搭建centos虚拟机并使用静态ip,局域网内可互通

    一 虚拟机镜像地址 我这里有镜像 二 目的 使用vmware搭建centos虚拟机集群 进行基础服务搭建 对系统业务提供服务支撑 三 效果 centos虚拟机ip不会自动改变 使用设置的静态ip 可以整个局域网互相访问 四 实现 1 宿主机
  • 密室逃生游戏【C语言】

    字符串 逻辑分析 小强在参加 密室逃生 游戏 当前关卡要求找到符合给定密码K 升序的不重复小写字母组成 的箱子 并给出箱子编号 箱子编号为1 N 每个箱子中都有一个字符串s 字符串由大写字母 小写字母 数字 标点符号 空格组成 需要在这些字
  • [从零开始学DeepFaceLab-13]: 使用-命令行八大操作步骤-第6步:模型的选择与训练 - 常见基本问题

    目录 前言 1 如何关闭训练 2 如何保存进度 大多情况下没有必要
  • NLP GPT算法笔记

    从这个意义上讲 我们可以说GPT 2本质上是键盘应用程序的下一个单词预测功能 但是它比您的手机具有更大 更复杂的功能 GPT 2在称为WebText的庞大40GB数据集上进行了训练 作为研究工作的一部分 OpenAI研究人员从互联网上进行了
  • 分布式Netty集群方案 加代码 SpringBoot 版

    目录 单机netty是怎么通信的 多节点集群netty是怎么通信的呢 netty集群是怎么搭建的呢 连接上的 client 的 channelId 怎么存入 redis 中 在集群模式中 客户端1向客户端2发送信息 演示效果 完整的讲解 n
  • unity_控制物体移动代码

    目录 2D游戏控制 简单的上下左右移动 第一种 使用Rigidbody2D 第二种 上下左右移动加上旋转 2D空战飞机的移动 汽车 坦克等移动 坦克的控制 2D游戏控制 简单的上下左右移动 第一种 使用Rigidbody2D using S
  • css3绘制扫描图片效果

    html
  • KMP算法(思想真的不复杂)

    在了解KMP之前 我们需要了解两个概念 字符串的前缀 和字符串的后缀 字符串的前缀 我举个例子你们就懂了 一个字符串abcde 它包含的前缀有 a ab abc abcd 字符串的后缀 bcde cde de e 知道这两个概念后 我们就可