当前位置: 首页 > 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…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)

2025年能源电力系统与流体力学国际会议&#xff08;EPSFD 2025&#xff09;将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会&#xff0c;EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

【入坑系列】TiDB 强制索引在不同库下不生效问题

文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

STM32标准库-DMA直接存储器存取

文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA&#xff08;Direct Memory Access&#xff09;直接存储器存取 DMA可以提供外设…...

在四层代理中还原真实客户端ngx_stream_realip_module

一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡&#xff08;如 HAProxy、AWS NLB、阿里 SLB&#xff09;发起上游连接时&#xff0c;将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后&#xff0c;ngx_stream_realip_module 从中提取原始信息…...

Java多线程实现之Callable接口深度解析

Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...

图表类系列各种样式PPT模版分享

图标图表系列PPT模版&#xff0c;柱状图PPT模版&#xff0c;线状图PPT模版&#xff0c;折线图PPT模版&#xff0c;饼状图PPT模版&#xff0c;雷达图PPT模版&#xff0c;树状图PPT模版 图表类系列各种样式PPT模版分享&#xff1a;图表系列PPT模板https://pan.quark.cn/s/20d40aa…...

现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?

现有的 Redis 分布式锁库&#xff08;如 Redisson&#xff09;相比于开发者自己基于 Redis 命令&#xff08;如 SETNX, EXPIRE, DEL&#xff09;手动实现分布式锁&#xff0c;提供了巨大的便利性和健壮性。主要体现在以下几个方面&#xff1a; 原子性保证 (Atomicity)&#xff…...

MySQL JOIN 表过多的优化思路

当 MySQL 查询涉及大量表 JOIN 时&#xff0c;性能会显著下降。以下是优化思路和简易实现方法&#xff1a; 一、核心优化思路 减少 JOIN 数量 数据冗余&#xff1a;添加必要的冗余字段&#xff08;如订单表直接存储用户名&#xff09;合并表&#xff1a;将频繁关联的小表合并成…...

并发编程 - go版

1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程&#xff0c;系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...

4. TypeScript 类型推断与类型组合

一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式&#xff0c;自动确定它们的类型。 这一特性减少了显式类型注解的需要&#xff0c;在保持类型安全的同时简化了代码。通过分析上下文和初始值&#xff0c;TypeSc…...