KMP算法

KMP

KMP 算法是一个快速查找匹配串的算法,它的作用其实就是本题问题:如何快速在「原字符串」中找到「匹配字符串」。

而 KMP 算法的复杂度为 O(m+n)实际上是O(N),因为O(M)不可能大于O(N)

KMP 之所以能够在 O(m+n)复杂度内完成查找,是因为其能在「非完全匹配」的过程中提取到有效信息进行复用,以减少「重复匹配」的消耗。

KMP解决的问题

KMP解决,如何查 m 是否是 字符串 s 的字串
暴力解法 : 尝试每一个字符串的开头,来模拟是否匹配 , 时间复杂度(M*N)

 public int strStr(String ss, String pp) {int n = ss.length(), m = pp.length();char[] s = ss.toCharArray(), p = pp.toCharArray();// 枚举原串的「发起点」for (int i = 0; i <= n - m; i++) {// 从原串的「发起点」和匹配串的「首位」开始,尝试匹配int a = i, b = 0;while (b < m && s[a] == p[b]) {a++;b++;}// 如果能够完全匹配,返回原串的「发起点」下标if (b == m) return i;}return -1;}

KMP利用了字符串 M 的 每个字符,的最长前缀与后缀匹配的长度信息来加速移动

举例 :
在这里插入图片描述

next数组: 将 i 位置的字符的最长前缀信息存到一个数组 , 这个数组就是next 数组
第一个字符因为:没有字符 所以规定为 -1
第二个字符因为:只有一个字符 所以规定为 0

先不说加速next的过程 ,我们能办到 将所有字符的信息都求出来
在这里插入图片描述

然后现在来讲解,如何根据 next数组来加速 字符串 s 与字符串 m 的匹配过程

如果从第一个字符开始 , 经典过程是, 如果我发现第 i 个字符不相等的时候 ,我 s 字符串 的下标 要跳到第 2 个字符(从第二个字符开始 ) , m 字符串的下标要跳回到 第一个字符重新匹配 ,这就是经典过程
而 KMP 是, 当发现 i 位置开头 ,一路往下比, 直到比到 S字符不与 Y 字符不一致的时候 , 我能根据 next 数组, 的最大长度, Y位置最长前缀的后面 ,而 S 字符位置不变

举例 :

在这里插入图片描述
为什么 Y能回跳? 而X字符不变?
在这里插入图片描述
在这里插入图片描述

好得,接下来我们讲解如何加速 next数组信息的过程
我们知晓: next数组存放的都是最长的前缀匹配长度, 所以当下一个字符想要求 最长前缀长度的时候,我们可以利用next数组的信息, 我们直接跳到,之前的最长前缀长度的下一位来与当前字符进行匹配, 如果匹配成功,我们当前字符的最长前缀长度就是匹配到的前一个的前缀长度加1 , 如果匹配失败, 那我们就继续先前跳,知道跳到不能跳了,写成0

package Str;public class KMP {//求一个字符串是不是另一个字符串的字串
//    整体复杂度O(N) 因为O(M)是不可能超过O(N)的public static int getIndexOf(String s,String m){if (s == null || m == null || m.length() >s.length() || m.length() < 1){return -1;}char[] str1 = s.toCharArray();char[] str2 = m.toCharArray();int i1= 0;int i2 = 0;int[] next = getNextArray(str2);//O(M)while (i1 < str1.length && i2 < str2.length){//i2 == str2.length的时候代表着,肯定匹配到了//O(N)if (str1[i1] == str2[i2]){//当前字符相等, 共同加加i1++;i2++;}else if (next[i2] == -1){//如果没有前缀和后缀匹配的,那没办法,只能往后走了i1++;}else {//如果不等,则找前缀和后缀最大的那个//要验证之前走过的是否有与str2匹配的情况i2 = next[i2];}}return i2 == str2.length ? i1-i2:-1;}public static int[] getNextArray(char[] ms){if (ms.length == 1){return new int[]{-1};}int[] next = new int[ms.length];next[0] = -1;next[1] = 0;int i = 2;int cn = 0;//即代表那个位置的值与i-1的值比while (i < next.length){if (ms[i-1] == ms[cn]){next[i++] = ++cn;}else if (cn > 0){//当前跳到cn位置的字符,和i-1位置的对应不上cn = next[cn];}else {//当cn为-1的时候,代表跳到了0下标的位置了next[i++] = 0;}}return next;}public static void main(String[] args) {String  s = "leetcode";String  m = "leeto";getIndexOf(s,m);}
}

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

selenium WebDriver 中的几种等待--sleep(),implicitly_wait(),WebDriverWait()

目录 强制等待:sleep() 隐式等待:implicitly_wait() 显示等待:WebDriverWait() 与until()或者until_not()方法结合使用 WebDriverWait与expected_conditions结合使用 显示等待,自定义等待条件 强制等待:sleep() import time sleep(5) #等待5秒 设置固定休眠时间&#x…

【菜鸟の笔记_利用Excel自动总结表格数据_自动链接word文本】

自动更新总结表格数据 1. 撰写原因2. 解决的问题3. Excel自动总结表格数据内容&#xff08;一段话&#xff09;。3.1问题引出3.2解决方式 4.Excel数据、总结内容&#xff0c;自动链接更新Word文本 1. 撰写原因 【GPT的答案】利用Excel自动总结表格数据有以下好处&#xff1a; …

哈工大计算机网络课程数据链路层协议详解之:多路访问控制(MAC)协议

哈工大计算机网络课程数据链路层协议详解之&#xff1a;多路访问控制&#xff08;MAC&#xff09;协议 在上一小节介绍完数据链路层功能和所提供的服务后&#xff0c;接下来我们介绍一个在数据链路层非常重要的一个协议&#xff1a;多路访问控制MAC协议。 多路访问控制主要是…

【机器人模拟-01】使用URDF在中创建模拟移动机器人

一、说明 在本教程中,我将向您展示如何使用通用机器人描述格式 (URDF)(机器人建模的标准 ROS 格式)创建模拟移动机器人。 机器人专家喜欢在构建机器人之前对其进行模拟,以测试不同的算法。您可以想象,使用物理机器人犯错的成本可能很高(例如,将移动机器人高速…

Python(二):Python简介

❤️ 专栏简介&#xff1a;本专栏记录了我个人从零开始学习Python编程的过程。在这个专栏中&#xff0c;我将分享我在学习Python的过程中的学习笔记、学习路线以及各个知识点。 ☀️ 专栏适用人群 &#xff1a;本专栏适用于希望学习Python编程的初学者和有一定编程基础的人。无…

mac 怎么批量修改文件后缀?

mac 批量修改文件后缀的方法教程~平时在电脑上使用文件的时候&#xff0c;经常需要对文件的后缀名进行修改&#xff0c;文件后缀名也就是文件扩展名&#xff0c;如果仅是单纯的修改文件后缀名&#xff0c;并不涉及格式转换的情况下&#xff0c;其实方法很简单&#xff0c;只需要…

【学会动态规划】使用最小花费爬楼梯(3)

目录 动态规划怎么学&#xff1f; 1. 题目解析 2. 算法原理 1. 状态表示 2. 状态转移方程 3. 初始化 4. 填表顺序 5. 返回值 3. 代码编写 写在最后&#xff1a; 动态规划怎么学&#xff1f; 学习一个算法没有捷径&#xff0c;更何况是学习动态规划&#xff0c; 跟我…

开源免费的多数据库工具Chat2DB

Chat2DB v1.0.11使用 当前使用的版本为1.0.11&#xff0c;目前已经更新到2.0.1版本。 一.Chat2DB介绍 Chat2DB 是一款开源免费的多数据库客户端工具。 能够将自然语言转换为SQL&#xff0c;也可以将SQL转换为自然语言。 支持windows、mac本地安装&#xff0c;也支持服务器端…

Redis 从入门到精通【进阶篇】之高可用哨兵机制(Redis Sentinel)详解

文章目录 0.前言1. 原理详解1.1. 哨兵机制的组建1.1. 哨兵是如何知道从库的信息 1.2. 主库下线的判定1.3. 哨兵集群选举1.4. 故障的转移 2. 总结3. Redis从入门到精通系列文章4. Redis哨兵模式面试题4. 1. 什么是Redis的哨兵模式&#xff1f;4. 2. 哨兵模式的优点是什么&#x…

TinyML4.3.3 拆分数据

将TinyML4.3.2 生成数据(Create Sin)文章中创建的1000个样本点数据拆分为训练集、验证集、测试集&#xff0c;其中训练集占60%&#xff0c;验证集占20%&#xff0c;测试集占20%。 新建一个cell&#xff0c;编辑代码&#xff1a; #Well use 60% of our data for training and …

ADManager Plus:企业自动化管理的利器

在当今数字化时代&#xff0c;企业管理面临着越来越多的挑战。为了提高效率、降低成本并确保信息安全&#xff0c;自动化管理成为了企业的首要选择。而在众多自动化管理工具中&#xff0c;ADManager Plus无疑是一款卓越的解决方案。本文将为您介绍ADManager Plus的功能与优势&a…

【QT/OpenCV】QT实现张正友相机标定

相机标定 01、相机标定02、OpenCV函数及其张正友标定法2.1、相机标定步骤2.2、相机标定相关函数2.2.1 提取角点--- findChessboardCorners2.2.2 亚像素角点提取1--- find4QuadCornerSubpix2.2.3 亚像素角点提取2--- cornerSubPix2.2.4 绘制内角点 --- drawChessboardCorners2.2…