KMP算法开荒
文章目录
- 一 、前言
- 二、 暴力解法
- 三、KMP算法原理
- 3.1 自动子串的指针
- 3.2 跳过多少个字符
- 3.3 next数组 - 暴力
- 3.4 next数组 - 求解
- 四 KMP实现
一 、前言
字符串匹配
import re
print(re.search('www', 'www.runoob.com').span()) # 在起始位置匹配
print(re.search('com', 'www.runoob.com').span()) # 不在起始位置匹配
SQL中的匹配
SELECT * FROM Persons
WHERE City LIKE '%lon%'
我们注意到这些都是需要用到字符串匹配的,我们再深入想一下,这些字符串是怎么匹配的呢?
二、 暴力解法
public class baoli {public static void main(String[] args) {String text = "ABABDABACDABABCABAB";//19String pattern = "ABABCABAB";//9int index = bruteForceMatch(text, pattern);if (index == -1) {System.out.println("Pattern not found in the text");} else {System.out.println("Pattern found at index " + index);}}public static int bruteForceMatch(String text, String pattern){int n = text.length();int m = pattern.length();for (int i = 0; i <= n - m; i++) {int j;for (j = 0; j < m; j++) {if (text.charAt(i + j) != pattern.charAt(j)) {break;}}if (j == m) {return i; // 匹配成功,返回起始位置}}return -1; // 匹配失败}
}
看到这种brute force暴力解法的时间复杂度为O(mn)
一个字一个字的匹配,一旦出错就匹配下一个

但是这样带来了巨大的浪费
三、KMP算法原理

KMP算法是用的这三位大佬的名字首字母,没有什么特殊含义
3.1 自动子串的指针

匹配失败,已经知道了前面读过了哪些char,所以移动子串的指针

3.2 跳过多少个字符

KMP算法会定义一个next数组,记录对应 可以跳过字符的个数
public static int kmpSearch(String text, String pattern) {int[] next = computeLPSArray(pattern);int i = 0; // text的指针int j = 0; // pattern的指针while (i < text.length()) {if (text.charAt(i) == pattern.charAt(j)) { // char匹配,都后移i++;j++;if (j == pattern.length()) {return i - j; // string匹配成功,返回起始位置}} else {if (j != 0) { // char匹配失败,pattern回退到上一个匹配的位置j = next[j - 1];} else { // 字符串第一个就匹配失败,直接后移i++;}}}return -1; // 匹配失败}
3.3 next数组 - 暴力

next数组:寻找子串中“相同前后缀的最长长度,不能是字符串本身”
那么如何获取这个next数组呢,当然首先可以想到for循环暴力求解
public static int[] bruteComputeLPSArray(String pattern) {int[] lps = new int[pattern.length()];int len = 0;for (int i = 1; i <= pattern.length() - 1; i++) {if (pattern.charAt(i) == pattern.charAt(len)) {len++;lps[i] = len;} else {if (len != 0) {len = lps[len - 1];i--;} else {lps[i] = 0;}}}return lps;}
3.4 next数组 - 求解

下一步相同,那么直接就是2+1
下一步不同呢?

左边这部分前后缀 = 右边这部分前后缀
直接在左边进行查找即可

于是又开始,寻找下一个char是否相同
public static int[] computeLPSArray(String pattern) {int[] next = new int[pattern.length()];int len = 0; // 最长公共前后缀的长度int i = 1; // pattern的指针while (i < pattern.length()) {if (pattern.charAt(i) == pattern.charAt(len)) {len++;next[i] = len;i++;} else {if (len != 0) {len = next[len - 1]; // 回退到前一个匹配的位置} else {next[i] = 0;i++;}}}return next;}
四 KMP实现
package com.KMP;public class KMPAlgorithm {public static void main(String[] args) {String text = "ABABDABACDABABCABAB";String pattern = "ABABCABAB";int index = kmpSearch(text, pattern);if (index == -1) {System.out.println("Pattern not found in the text");} else {System.out.println("Pattern found at index " + index);}}public static int kmpSearch(String text, String pattern) {int[] next = computeLPSArray(pattern);int i = 0; // text的指针int j = 0; // pattern的指针while (i < text.length()) {if (text.charAt(i) == pattern.charAt(j)) { // char匹配,都后移i++;j++;if (j == pattern.length()) {return i - j; // string匹配成功,返回起始位置}} else {if (j != 0) { // char匹配失败,pattern回退到上一个匹配的位置j = next[j - 1];} else { // (j == 0) 字符串第一个就匹配失败,直接后移i++;}}}return -1; // 匹配失败}public static int[] computeLPSArray(String pattern) {int[] next = new int[pattern.length()];int len = 0; // 最长公共前后缀的长度int i = 1; // pattern的指针while (i < pattern.length()) {if (pattern.charAt(i) == pattern.charAt(len)) {len++;next[i] = len;i++;} else {if (len != 0) {len = next[len - 1]; // 回退到前一个匹配的位置} else {next[i] = 0;i++;}}}return next;}public static int[] bruteComputeLPSArray(String pattern) {int[] lps = new int[pattern.length()];int len = 0;for (int i = 1; i <= pattern.length() - 1; i++) {if (pattern.charAt(i) == pattern.charAt(len)) {len++;lps[i] = len;} else {if (len != 0) {len = lps[len - 1];i--;} else {lps[i] = 0;}}}return lps;}
}相关文章:
KMP算法开荒
文章目录 一 、前言二、 暴力解法三、KMP算法原理3.1 自动子串的指针3.2 跳过多少个字符3.3 next数组 - 暴力3.4 next数组 - 求解 四 KMP实现 一 、前言 字符串匹配 import re print(re.search(www, www.runoob.com).span()) # 在起始位置匹配 print(re.search(com, www.run…...
XXL-JOB(2)
Glue模式 任务以源码的形式去维护调度中心,支持实时编译,无需指定JobHandler。 实际上是继承自JobHandler的java类代码,在执行器中运行,可以使用Resource/Autowire注入执行器里中的其他服务. 在执行器中添加service Service p…...
Linux常用命令_网络命令、关机重启命令
文章目录 1. 网络命令1.1 网络命令: write1.2 网络命令: wall1.3 网络命令: ping1.4 网络命令: ifconfig1.5 网络命令: mail1.6 网络命令: last1.7 网络命令: lastlog1.8 网络命令: traceroute1.9 网络命令: netstat1.10 网络命令: setup1.11 挂载命令 2. 关机重启命令2.1 shut…...
用Cmake build OpenCV后,在VS中查看OpenCV源码的方法(环境VS2022+openCV4.8.0) Part I
用Cmake build OpenCV后,在VS中查看OpenCV源码的方法 Part I 写在最前面,最近这段时间的工作需要用opencv,不仅是调包,还要能够看到opencv的源码。然后就跟着网上的教程实现了一遍,在实现过程中,遇到了不少…...
如何使用Docker搭建ZooKeepe集群
1、拉取镜像 # docker pull zookeeper:3.7.12、创建网络 Docker创建容器时默认采用bridge网络,自行分配ip,不允许自己指定。在实际部署中,需要指定容器ip,不允许其自行分配ip,尤其在搭建集群时。可以通过docker netw…...
【javaweb】学习日记Day3 - Ajax 前后端分离开发 入门
目录 一、Ajax 1、简介 2、Axios (没懂 暂留) (1)请求方式别名 (2)发送get请求 (3)发送post请求 (4)案例 二、前端工程化 1、Vue项目-目录结构 2、…...
SQL注入漏洞复现:探索不同类型的注入攻击方法
这篇文章旨在用于网络安全学习,请勿进行任何非法行为,否则后果自负。 准备环境 sqlilabs靶场 安装:详细安装sqlmap详细教程_sqlmap安装教程_mingzhi61的博客-CSDN博客 一、基于错误的注入 注入讲解 介绍 基于错误的注入(Err…...
大彩串口屏使用记录
写在最前面 屏幕型号 DC10600M070 IDE VisualTFT(官方) VSCode(lua编程) 用之前看一下官方那个1小时的视频教程就大概懂控件怎么用了,用官方的软件VisualTFT很简单 本文只是简单记录遇到的一些坑 lua编辑器 VisualTF…...
Qt http 的认证方式以及简单实现
http 的认证方式 基本认证(Basic Authentication): 基本认证是最简单的HTTP认证方式。客户端在请求头中使用Base64编码的用户名和密码进行身份验证由于仅使用Base64编码,基本认证并不安全,因此建议与HTTPS一起使用,以…...
【图像分割】实现snake模型的活动轮廓模型以进行图像分割研究(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
【MongoDB系列】1.MongoDB 6.x 在 Windows 和 Linux 下的安装教程(详细)
本文主要介绍 MongoDB 最新版本 6.x 在Windows 和 Linux 操作系统下的安装方式,和过去 4.x 、5.x 有些许不同之处,供大家参考。 Windows 安装 进入官网下载 Mongodb 安装包,点此跳转,网站会自动检测当前操作系统提供最新的版本&…...
5.网络原理之初识
文章目录 1.网络发展史1.1独立模式1.2网络互连1.3局域网LAN1.3.1基于网线直连1.3.2基于集线器组建1.3.3基于交换机组建1.3.4基于交换机和路由器组建1.3.4.1路由器和交换机区别 1.4广域网WAN 2.网络通信基础2.1IP地址2.2端口号2.3认识协议2.4五元组2.5 协议分层2.5.1 分层的作用…...
【Linux】进程状态|僵尸进程|孤儿进程
前言 本文继续深入讲解进程内容——进程状态。 一个进程包含有多种状态,有运行状态,阻塞状态,挂起状态,僵尸状态,死亡状态等等,其中,阻塞状态还包含深度睡眠和浅度睡眠状态。 个人主页ÿ…...
ASEMI快恢复二极管APT80DQ60BG特点应用
编辑-Z APT80DQ60BG参数描述: 型号:APT80DQ60BG 最大峰值反向电压(VRRM):600V 最大直流阻断电压VR(DC):600V 平均整流正向电流(IF):80A 非重复峰值浪涌电流(IFSM):600A 工作接点温度和储存温度(TJ, …...
【Python爬虫】使用代理ip进行网站爬取
前言 使用代理IP进行网站爬取可以有效地隐藏你的真实IP地址,让网站难以追踪你的访问行为。本文将介绍Python如何使用代理IP进行网站爬取的实现,包括代理IP的获取、代理IP的验证、以及如何把代理IP应用到爬虫代码中。 1. 使用代理IP的好处 在进行网站爬…...
识别图片中的文字
前言 PearOCR 是一款免费无限制网页版文字识别工具。 优点如下: 免费:完全免费,没有任何次数、大小限制,可以无限使用; 安全:全部数据本地运算,所有图片均不会被上传; 智能…...
第七章:借阅管理【基于Servlet+JSP的图书管理系统】
借阅管理 1. 借书卡 1.1 查询借书卡 借书卡在正常的CRUD操作的基础上,我们还需要注意一些特殊的情况。查询信息的时候。如果是管理员则可以查询所有的信息,如果是普通用户则只能查看自己的信息。这块的控制在登录的用户信息 然后就是在Dao中处理的时候需…...
算法 for GAMES
栈 #include <iostream> #include <stack>int main() {std::stack<int> intStack;// 压入元素到堆栈intStack.push(5);intStack.push(10);intStack.push(15);// 查看堆栈顶部元素std::cout << "Top element: " << intStack.top() <…...
自研分布式IM-HubuIM RFC草案
HubuIM RFC草案 消息协议设计 基本协议 评估标准 【性能】协议传输效率,尽可能降低端到端的延迟,延迟高于200ms用户侧就会有所感知 【兼容】既要向前兼容也要向后兼容 【存储】减少消息包的大小,降低空间占用率,一个字节在亿…...
tableau基础学习1:数据源与绘图
文章目录 读取数据常用绘图方法1. 柱状图2. 饼图3. 散点图4. 热力图 第一部分是一些较容易上手的内容,以及比较常见的可视化内容,包括:柱状图、饼图、散点图与热力图 读取数据 打开界面后,选择数据源之后就可以导入数据…...
龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...
STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...
el-switch文字内置
el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...
React19源码系列之 事件插件系统
事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...
第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...
什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...
关键领域软件测试的突围之路:如何破解安全与效率的平衡难题
在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件,这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下,实现高效测试与快速迭代?这一命题正考验着…...
SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)
上一章用到了V2 的概念,其实 Fiori当中还有 V4,咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务),代理中间件(ui5-middleware-simpleproxy)-CSDN博客…...
C++使用 new 来创建动态数组
问题: 不能使用变量定义数组大小 原因: 这是因为数组在内存中是连续存储的,编译器需要在编译阶段就确定数组的大小,以便正确地分配内存空间。如果允许使用变量来定义数组的大小,那么编译器就无法在编译时确定数组的大…...
Fabric V2.5 通用溯源系统——增加图片上传与下载功能
fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...
