当前位置: 首页 > news >正文

KMP算法总结

KMP算法总结

  • BF算法引导
    • BF算法步骤(图片演示)
    • 代码演示
  • KMP算法
    • 推next数组
    • 代码演示

BF算法引导

BF算法是一个暴力的字符串匹配算法,时间复杂度是o(m*n)
假设主串和子串分别为
在这里插入图片描述

我们想要找到子串在主串的位置
BF算法核心:BF算法就是同时遍历子串和主串,如果不相同就将子串指针回退到首位,主串指针回退到这次遍历的起点的下一个位置
我们指定主串的指针为i,子串的指针为j,如下图:
在这里插入图片描述

BF算法步骤(图片演示)

匹配的过程,我将用图来阐释:
1.第一趟
在这里插入图片描述
i++;
j++;
在这里插入图片描述
i++;
j++;
在这里插入图片描述
这时我们发现,i和j指向的内容不一样了
这时我们进入下一趟
2.第二趟
i=i-j+1;
(这里就是主串指针回退到这次遍历的起点的下一个位置,因为每次都是i和j同时走,但j每次都是从0开始走,j同时记录了i每次走了多少步,i-j就是回退到这一趟的起点,但这个起点我们试过了,就是+1,从下一个位置开始试)
j=0;
在这里插入图片描述

这里我们发现,i和j指向的内容不一样了
这时我们进入下一趟
3.第三趟

i=i-j+1;
j=0;
在这里插入图片描述
i++;
j++;
在这里插入图片描述
i++;
j++;
在这里插入图片描述
这里我们发现,i和j指向的内容不一样了
这时我们进入下一趟
4.第四趟
i=i-j+1;
j=0;
在这里插入图片描述
这里我们发现,i和j指向的内容不一样了
这时我们进入下一趟
5.第五趟
i=i-j+1;
j=0;
在这里插入图片描述
这里我们发现,i和j指向的内容不一样了
这时我们进入下一趟
6.第六趟
i=i-j+1;
j=0;
在这里插入图片描述
i++;
j++;
在这里插入图片描述
i++;
j++;
在这里插入图片描述
i++;
j++;
在这里插入图片描述
i++;
j++;
在这里插入图片描述
这时我们发现主串和子串都遍历结束(这个例子有点奇怪,一般只有一个遍历结束,整个程序就能判断是否有子串,并找到子串位置)
我们不难发现只有当子串遍历完,才能说明主串有这个子串

代码演示

public class BF {static int Bf(String S,String s){//空字符串if(S==null||s==null){return -1;}//主串长度int SUM=S.length();//子串长度int sum=s.length();//字符串长度为0if(SUM==0||sum==0){return -1;}//指针int i=0;int j=0;while (i<SUM&&j<sum){if(S.charAt(i)==s.charAt(j)){i++;j++;}else {i=i-j+1;j=0;}}if(j>=sum){return i-j;}return -1;}public static void main(String[] args) {System.out.println(Bf("aacascscc","ac"));}
}

在这里插入图片描述

KMP算法

KMP也是一种字符串匹配算法,只不过他利用了遍历过的串的信息,减少了趟数,最重要就是理解他怎么利用信息
举个例子
在这里插入图片描述
我们指定主串的指针为i,子串的指针为j,如下图:
在这里插入图片描述
i++;
j++;
一直到匹配不正确的地方
在这里插入图片描述

我们想让I指针停下来,只移动j指针,(这是我们想的就是这时i要回退,我们不想让他回退,但又不能丢下前面的,所以我们看前面还有什么能用上的)这时,我们遍历了主串的ABAB ,和子串的ABAB,他们两个肯定是相同的因为刚刚遍历了,如果不相同肯定会停下来,如果是BF算法我们肯定会i=i-j+1;j++;但现在我们想利用我们遍历过的ABAB的信息,我的方法是向后拖拽子串,只要发生拖拽,主串的开头A和子串结尾的B肯定是用不上了,我们必须求的是主串的(从后面开始,如果是从BAB开始算前缀即使前面匹配后面不匹配也没有用)后缀和子串的(从前面开始)前缀,(这里就是为什么求主串的后缀和子串的前缀)
在这里插入图片描述
在这里插入图片描述
拖拽两次,我们发现主串和子串有AB重叠,这时我们就能继续遍历了(我的思考是这里我们利用了ABAB重叠的信息,省去了i指针回退到主串的下标为2,子串下标为0的地方一点点++匹配,而主串前面AB我们发现没有匹配,所以就丢弃)
在这里插入图片描述
现在我们想知道怎么利用匹配过的信息,怎么一下就能找到拖拽后j到的位置
就要引入next数组,来存储j指针在每个位置匹配失败要回退到哪

推next数组

假设有这样一个字符串
在这里插入图片描述
规则如下:
在这里插入图片描述
前两个下标为0,1的就是固定的,
从下标为2开始,假设匹配失败了,ab内找以a开头以b结尾,除了本身没有这样的字符串,回退到0,
下标为3时,假设匹配失败了,aba内找以a开头以a结尾,有这样的字符串,回退到1,
在这里插入图片描述
下标为3时,假设匹配失败了,abab内找以a开头以b结尾,有这样的字符串,回退到2,
后面的自行计算,结果为
在这里插入图片描述
给个例题,请求出他的next数组:
在这里插入图片描述
接下来我们进行一个推理
在这里插入图片描述
设原字符数组为p【】
如上图所示,next【i】=k,假设p【i】==p【k】如上图所示,那么
p【0】…p【k-1】==p【x】…p【i-1】
又已知k-0i-x得到xi-k
p【0】…p【k-1】==p【i-k】…p【i-1】
又因为p【i】==p【k】所以p【0】…p【k】==p【i-k】…p【i】
所以next【i+1】==k+1
推出来的意思是p【8】这个前面有abc和前面的abc匹配p【3】和p【8】又相等那么p【9】找前面的匹配时直接p【8】前面找到的abc加p【8】;
在这里插入图片描述
如上图所示,next【i】=k,假设p【i】!=p【k】如上图所示,那么
不是我们要找的,我们就再回退到k=0这时p【i】==p【k】
这时我们又能用next【i+1】==k+1,next【6】=k+1=1

代码演示

public class KMP {public static void main(String[] args) {System.out.println(KMP("CSA","SA"));}public static int KMP (String s, String sub){int lens = s.length(), lensub = sub.length();int[] next = new int[lensub];//next数组  存放匹配不上的子串要跳跃的下标getNext(next, sub);int i = 0, j = 0;// i 遍历主串, j 遍历子串while (i < lens && j < lensub) {if (j == -1 || s.charAt(i) == sub.charAt(j)) {i++;j++;//逐一比较,相同的看下一个//当子串的第一个字符就与主串的字符不相等时,j++为0,i向后移动一位} else {j = next[j];}}if (j == lensub) {return i - j;//上面while循环结束条件是因为   遍历发现子串所有均与主串相等} else {return -1;}}public static void getNext ( int[] next, String sub){next[0] = -1;next[1] = 0;//固定int i = 2;//i表示当前所求next数组的下标int k = 0;//比较是否相等的前一项while (i < sub.length()) {if (k == -1 || sub.charAt(i - 1) == sub.charAt(k)) {//就是一直回退直到就是说没有利用的重叠部分就是k=-1next[i] = k + 1;//当k==-1时,证明【0】与【j-1】里无相等字符,k++为0,i移向下一位k++;i++;} else {k = next[k];}}}}

之后如果有新的想法会及时补充,大家如果有不同见解欢迎评论区留言
在这里插入图片描述

相关文章:

KMP算法总结

KMP算法总结 BF算法引导BF算法步骤&#xff08;图片演示&#xff09;代码演示 KMP算法推next数组代码演示 BF算法引导 BF算法是一个暴力的字符串匹配算法&#xff0c;时间复杂度是o&#xff08;m*n&#xff09; 假设主串和子串分别为 我们想要找到子串在主串的位置 BF算法核…...

消息中间件ActiveMQ介绍

一、消息中间件的介绍 介绍 ​ 消息队列 是指利用 高效可靠 的 消息传递机制 进行与平台无关的 数据交流&#xff0c;并基于 数据通信 来进行分布式系统的集成。 特点(作用) 应用解耦 异步通信 流量削峰 (海量)日志处理 消息通讯 …... 应用场景 根据消息队列的特点&a…...

【100天精通python】Day9:数据结构_字典、集合

目录 目录 1 字典 1.1 字典的基本操作示例 1.2 字典推导式 2 集合 2.1 集合的常用操作示例 3 列表、元组、字典、集合的区别 1 字典 在Python中&#xff0c;字典&#xff08;Dictionary&#xff09;是一种无序的数据结构&#xff0c;用于存储键值对的集合。每个…...

上海VR全景展示,快速了解VR全景拍摄

导语&#xff1a; 随着科技的不断进步&#xff0c;虚拟现实技术的应用日益广泛。在这其中&#xff0c;VR全景图片作为一种数字化助力的全景拍摄方式&#xff0c;正逐渐成为人们关注的焦点。通过数字化技术&#xff0c;VR全景图片能够以360度全方位的视角呈现真实的场景&#x…...

VScode远程不用再输入密码操作

安装插件remote development 1.先检查自己电脑上有没有生成一对公钥和私钥。&#xff08;一般会在这个目录&#xff09; 如果没有的话就自己生成一下。 打开命令行输入以下命令 ssh-keygen -t rsa2.在虚拟机中先看一下有没有公钥和私钥。如果没有的话就自己生成一下。 打开…...

MyBatis基本用法-@TableId

TableId 注解是 MyBatis Plus 框架中用于标识实体类中的主键字段的注解&#xff0c;它有一些可选的配置项。下面是详细说明&#xff1a; 首先&#xff0c;需要在项目中添加 MyBatis Plus 的依赖。可以在项目的 pom.xml 文件中添加以下代码&#xff1a; <dependency><…...

React AntDesign写一个导出数据的提示语 上面有跳转的路径,或者点击知道了,关闭该弹层

效果如下&#xff1a; 代码如下&#xff1a; ForwardDataCenterModal(_blank);export const ForwardDataCenterModal (target?: string) > {let contentBefore React.createElement(span, null, 数据正在处理中&#xff0c;请稍后前往);let contentAfter React.creat…...

小红书课程发光社群知识库,点亮哥专为超级个体设计解决方案

小红书课程点亮哥知识库 开创了学习小红书教育培训先河 针对超级个体轻创业的学习需求场景 创新推出了“知识库全新学习方式”。 一个人如何做好小红书? 超级个体轻创业,如何做好小红书? 通过打造个人IP、或者塑造老板个人品牌,来实现互联网变现,如何做好小红书? 就像挑…...

基于SpringBoot+Vue的摄影跟拍预定管理系统设计与实现(源码+lw+部署文档等)

博主介绍&#xff1a; 大家好&#xff0c;我是一名在Java圈混迹十余年的程序员&#xff0c;精通Java编程语言&#xff0c;同时也熟练掌握微信小程序、Python和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架…...

HCIA 第二课总结

配置网络设备的明文密钥实验组网 实验拓扑 将一个路由器使用配置口进行连接 sys #进入系统视图模式 sysname RTA #给设备命名 user-interface console 0 #进入用户接口配置界面 authentication-mode password #配置认证模式为密钥认证 set authentication password ciphe…...

linux-------联网下载文件和配置

1.Wget Wget是一个十分常用命令行下载工具&#xff0c;多数Linux发行版本都默认包含这个工具。如果没有安装可在http://www.gnu.org/software/wget/wget.html下载最新版本&#xff0c;并使用如下命令编译安装&#xff1a; 1.#tar zxvf wget-1.9.1.tar.gz #cd wget-1.9.1 #./c…...

字典树Trie

Trie树又称字典树&#xff0c;前缀树。是一种可以高效查询前缀字符串的树&#xff0c;典型应用是用于统计&#xff0c;排序和保存大量的字符串&#xff08;但不仅限于字符串&#xff09;&#xff0c;所以经常被搜索引擎系统用于文本词频统计。 它的优点是&#xff1a;利用字符串…...

算法之桶排序算法

桶排序的基本思想是&#xff1a; 把数组 arr 划分为 n 个大小相同子区间&#xff08;桶&#xff09;&#xff0c;每个子区间各自排序&#xff0c;最 后合并 。计数排序是桶排序的一种特殊情况&#xff0c;可以把计数排序当成每个桶里只有一个元素的情况。 1.找出待排序数组中的…...

读kafka生产端源码,窥kafka设计之道(下)

背景 在上一篇文章《读kafka生产端源码&#xff0c;窥kafka设计之道&#xff08;上&#xff09;》 留下了kafka设计上比较优秀的一个点&#xff1b;内存的循环使用。本篇文章准备盘盘它。 好奇 为什么 kafka减少发送消息时向JVM频繁申请内存&#xff0c;就可以降低JVM GC的执…...

Pytorch个人学习记录总结 06

目录 神经网络-卷积层 torch.nn.Conv2d 神经网络-最大池化的使用 torch.nn.MaxPool2d 神经网络-卷积层 torch.nn.Conv2d torch.nn.Conv2d的官方文档地址 CLASS torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride1, padding0, dilation1, groups1, biasTrue,…...

Rust之泛型、特性和生命期(四):验证有生存期的引用

开发环境 Windows 10Rust 1.71.0 VS Code 1.80.1 项目工程 这里继续沿用上次工程rust-demo 验证具有生存期的引用 生存期是我们已经在使用的另一种泛型。生存期不是确保一个类型具有我们想要的行为&#xff0c;而是确保引用在我们需要时有效。 我们在第4章“引用和借用”一…...

kubesphere安装中间件

kubesphere安装mysql 创建configMap [client] default-character-setutf8mb4[mysql] default-character-setutf8mb4[mysqld] init_connectSET collation_connection utf8mb4_unicode_ci init_connectSET NAMES utf8mb4 character-set-serverutf8mb4 collation-serverutf8mb4_…...

zookeeper学习(二) 集群模式安装

前置环境 三台centos7服务器 192.168.2.201 192.168.2.202 192.168.2.150三台服务器都需要安装jdk1.8以上zookeeper安装包 安装jdk 在单机模式已经描述过&#xff0c;这里略过&#xff0c;有需要可以去看单机模式中的这部分&#xff0c;注意的是三台服务器都需要安装 安装…...

选择合适的图表,高效展现数据魅力

随着大数据时代的来临&#xff0c;数据的重要性愈发凸显&#xff0c;数据分析和可视化成为了决策和传递信息的重要手段。在数据可视化中&#xff0c;选择合适的图表是至关重要的一环&#xff0c;它能让数据更加生动、直观地呈现&#xff0c;为观众提供更有说服力的信息。本文将…...

springboot自动装配

SPI spi &#xff1a; service provider interface &#xff1a; 是java的一种服务提供机制&#xff0c;spi 允许开发者在不修改代码的情况下&#xff0c;为某个接口提供实现类&#xff0c;来扩展应用程序 将实现类独立到配置文件中&#xff0c;通过配置文件控制导入&#xff…...

全球首个30米分辨率湿地数据集(2000—2022)

数据简介 今天我们分享的数据是全球30米分辨率湿地数据集&#xff0c;包含8种湿地亚类&#xff0c;该数据以0.5X0.5的瓦片存储&#xff0c;我们整理了所有属于中国的瓦片名称与其对应省份&#xff0c;方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

第25节 Node.js 断言测试

Node.js的assert模块主要用于编写程序的单元测试时使用&#xff0c;通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试&#xff0c;通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...

ardupilot 开发环境eclipse 中import 缺少C++

目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...

C# SqlSugar:依赖注入与仓储模式实践

C# SqlSugar&#xff1a;依赖注入与仓储模式实践 在 C# 的应用开发中&#xff0c;数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护&#xff0c;许多开发者会选择成熟的 ORM&#xff08;对象关系映射&#xff09;框架&#xff0c;SqlSugar 就是其中备受…...

Java入门学习详细版(一)

大家好&#xff0c;Java 学习是一个系统学习的过程&#xff0c;核心原则就是“理论 实践 坚持”&#xff0c;并且需循序渐进&#xff0c;不可过于着急&#xff0c;本篇文章推出的这份详细入门学习资料将带大家从零基础开始&#xff0c;逐步掌握 Java 的核心概念和编程技能。 …...

全志A40i android7.1 调试信息打印串口由uart0改为uart3

一&#xff0c;概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本&#xff1a;2014.07&#xff1b; Kernel版本&#xff1a;Linux-3.10&#xff1b; 二&#xff0c;Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01)&#xff0c;并让boo…...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习

禁止商业或二改转载&#xff0c;仅供自学使用&#xff0c;侵权必究&#xff0c;如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...

AGain DB和倍数增益的关系

我在设置一款索尼CMOS芯片时&#xff0c;Again增益0db变化为6DB&#xff0c;画面的变化只有2倍DN的增益&#xff0c;比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析&#xff1a; 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...

C#中的CLR属性、依赖属性与附加属性

CLR属性的主要特征 封装性&#xff1a; 隐藏字段的实现细节 提供对字段的受控访问 访问控制&#xff1a; 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性&#xff1a; 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑&#xff1a; 可以…...

Python Einops库:深度学习中的张量操作革命

Einops&#xff08;爱因斯坦操作库&#xff09;就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库&#xff0c;用类似自然语言的表达式替代了晦涩的API调用&#xff0c;彻底改变了深度学习工程…...