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

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模式 任务以源码的形式去维护调度中心&#xff0c;支持实时编译&#xff0c;无需指定JobHandler。 实际上是继承自JobHandler的java类代码&#xff0c;在执行器中运行&#xff0c;可以使用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后&#xff0c;在VS中查看OpenCV源码的方法 Part I 写在最前面&#xff0c;最近这段时间的工作需要用opencv&#xff0c;不仅是调包&#xff0c;还要能够看到opencv的源码。然后就跟着网上的教程实现了一遍&#xff0c;在实现过程中&#xff0c;遇到了不少…...

如何使用Docker搭建ZooKeepe集群

1、拉取镜像 # docker pull zookeeper:3.7.12、创建网络 Docker创建容器时默认采用bridge网络&#xff0c;自行分配ip&#xff0c;不允许自己指定。在实际部署中&#xff0c;需要指定容器ip&#xff0c;不允许其自行分配ip&#xff0c;尤其在搭建集群时。可以通过docker netw…...

【javaweb】学习日记Day3 - Ajax 前后端分离开发 入门

目录 一、Ajax 1、简介 2、Axios &#xff08;没懂 暂留&#xff09; &#xff08;1&#xff09;请求方式别名 &#xff08;2&#xff09;发送get请求 &#xff08;3&#xff09;发送post请求 &#xff08;4&#xff09;案例 二、前端工程化 1、Vue项目-目录结构 2、…...

SQL注入漏洞复现:探索不同类型的注入攻击方法

这篇文章旨在用于网络安全学习&#xff0c;请勿进行任何非法行为&#xff0c;否则后果自负。 准备环境 sqlilabs靶场 安装&#xff1a;详细安装sqlmap详细教程_sqlmap安装教程_mingzhi61的博客-CSDN博客 一、基于错误的注入 注入讲解 介绍 基于错误的注入&#xff08;Err…...

大彩串口屏使用记录

写在最前面 屏幕型号 DC10600M070 IDE VisualTFT&#xff08;官方&#xff09; VSCode&#xff08;lua编程&#xff09; 用之前看一下官方那个1小时的视频教程就大概懂控件怎么用了&#xff0c;用官方的软件VisualTFT很简单 本文只是简单记录遇到的一些坑 lua编辑器 VisualTF…...

Qt http 的认证方式以及简单实现

http 的认证方式 基本认证&#xff08;Basic Authentication&#xff09;: 基本认证是最简单的HTTP认证方式。客户端在请求头中使用Base64编码的用户名和密码进行身份验证由于仅使用Base64编码&#xff0c;基本认证并不安全&#xff0c;因此建议与HTTPS一起使用&#xff0c;以…...

【图像分割】实现snake模型的活动轮廓模型以进行图像分割研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

【MongoDB系列】1.MongoDB 6.x 在 Windows 和 Linux 下的安装教程(详细)

本文主要介绍 MongoDB 最新版本 6.x 在Windows 和 Linux 操作系统下的安装方式&#xff0c;和过去 4.x 、5.x 有些许不同之处&#xff0c;供大家参考。 Windows 安装 进入官网下载 Mongodb 安装包&#xff0c;点此跳转&#xff0c;网站会自动检测当前操作系统提供最新的版本&…...

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】进程状态|僵尸进程|孤儿进程

前言 本文继续深入讲解进程内容——进程状态。 一个进程包含有多种状态&#xff0c;有运行状态&#xff0c;阻塞状态&#xff0c;挂起状态&#xff0c;僵尸状态&#xff0c;死亡状态等等&#xff0c;其中&#xff0c;阻塞状态还包含深度睡眠和浅度睡眠状态。 个人主页&#xff…...

ASEMI快恢复二极管APT80DQ60BG特点应用

编辑-Z APT80DQ60BG参数描述&#xff1a; 型号&#xff1a;APT80DQ60BG 最大峰值反向电压(VRRM)&#xff1a;600V 最大直流阻断电压VR(DC)&#xff1a;600V 平均整流正向电流(IF)&#xff1a;80A 非重复峰值浪涌电流(IFSM)&#xff1a;600A 工作接点温度和储存温度(TJ, …...

【Python爬虫】使用代理ip进行网站爬取

前言 使用代理IP进行网站爬取可以有效地隐藏你的真实IP地址&#xff0c;让网站难以追踪你的访问行为。本文将介绍Python如何使用代理IP进行网站爬取的实现&#xff0c;包括代理IP的获取、代理IP的验证、以及如何把代理IP应用到爬虫代码中。 1. 使用代理IP的好处 在进行网站爬…...

识别图片中的文字

前言 PearOCR 是一款免费无限制网页版文字识别工具。 优点如下&#xff1a; 免费&#xff1a;完全免费&#xff0c;没有任何次数、大小限制&#xff0c;可以无限使用&#xff1b; 安全&#xff1a;全部数据本地运算&#xff0c;所有图片均不会被上传&#xff1b; 智能&#xf…...

第七章:借阅管理【基于Servlet+JSP的图书管理系统】

借阅管理 1. 借书卡 1.1 查询借书卡 借书卡在正常的CRUD操作的基础上&#xff0c;我们还需要注意一些特殊的情况。查询信息的时候。如果是管理员则可以查询所有的信息&#xff0c;如果是普通用户则只能查看自己的信息。这块的控制在登录的用户信息 然后就是在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草案 消息协议设计 基本协议 评估标准 【性能】协议传输效率&#xff0c;尽可能降低端到端的延迟&#xff0c;延迟高于200ms用户侧就会有所感知 【兼容】既要向前兼容也要向后兼容 【存储】减少消息包的大小&#xff0c;降低空间占用率&#xff0c;一个字节在亿…...

tableau基础学习1:数据源与绘图

文章目录 读取数据常用绘图方法1. 柱状图2. 饼图3. 散点图4. 热力图 第一部分是一些较容易上手的内容&#xff0c;以及比较常见的可视化内容&#xff0c;包括&#xff1a;柱状图、饼图、散点图与热力图 读取数据 打开界面后&#xff0c;选择数据源之后就可以导入数据&#xf…...

WebPages 发布

WebPages 发布 引言 随着互联网技术的飞速发展,Web技术已经成为现代信息社会不可或缺的一部分。WebPages作为Web技术的重要应用,旨在为用户提供高效、便捷的网页浏览体验。本文将详细介绍WebPages的发布过程,包括技术选型、功能设计、性能优化以及用户体验等方面。 技术选…...

毕业设计实战:基于SSM+MySQL的税务门户网站设计与实现指南

毕业设计实战&#xff1a;基于SSMMySQL的税务门户网站设计与实现指南 在开发“基于SSMMySQL的税务门户网站”毕业设计时&#xff0c;曾因政策文件收藏表未通过用户ID与政策文件ID双外键关联踩过关键坑——初期仅设计收藏编号、收藏时间等基础字段&#xff0c;未与用户表、政策文…...

北斗高精度数据解算:破解城市峡谷/长基线/无网区难题,从毫米级定位到自动化交付——(GAMIT/GLOBK底层核心解算技术方法)

北斗三号全面应用已至深水区&#xff0c;一线甲级测绘单位与科研院所正面临三重实战拷问&#xff1a;城市峡谷多路径干扰下如何实现毫米级收敛&#xff1f;西部高海拔无网区如何依托离线精密轨道完成长基线高精度解算&#xff1f;国家重大工程"零误差"标准下&#xf…...

机械键盘连击终极解决方案:Keyboard Chatter Blocker全方位技术解析

机械键盘连击终极解决方案&#xff1a;Keyboard Chatter Blocker全方位技术解析 【免费下载链接】KeyboardChatterBlocker A handy quick tool for blocking mechanical keyboard chatter. 项目地址: https://gitcode.com/gh_mirrors/ke/KeyboardChatterBlocker Keyboar…...

4阶段构建企业级离线文档处理平台:从问题诊断到性能优化全指南

4阶段构建企业级离线文档处理平台&#xff1a;从问题诊断到性能优化全指南 【免费下载链接】WeKnora LLM-powered framework for deep document understanding, semantic retrieval, and context-aware answers using RAG paradigm. 项目地址: https://gitcode.com/GitHub_Tr…...

手把手调试:从V8引擎的ArrayBuffer到WebAssembly,一步步拆解Chrome CVE-2020-6507漏洞利用链

深入解析Chrome V8引擎漏洞利用&#xff1a;从ArrayBuffer到WebAssembly的内存操控实战 浏览器安全研究领域近年来持续升温&#xff0c;其中V8引擎作为Chrome和Node.js的核心组件&#xff0c;其安全性直接影响着数十亿用户。本文将带您深入探索一个典型V8漏洞&#xff08;CVE-2…...

无需配置环境!MinerU镜像一键部署,即刻体验智能文档解析

无需配置环境&#xff01;MinerU镜像一键部署&#xff0c;即刻体验智能文档解析 1. 为什么选择智能文档解析&#xff1f; 在日常办公和学习中&#xff0c;我们经常需要处理各种文档资料&#xff1a;PDF报告、扫描合同、学术论文、财务报表等。传统方式要么需要手动输入&#…...

大模型本地推理显卡怎么选?实测Tesla P40、Titan RTX和RTX A3000的性价比之战

大模型本地推理显卡选购实战指南&#xff1a;Tesla P40、Titan RTX与RTX A3000深度横评 当你在深夜调试一个70亿参数的LLM模型时&#xff0c;突然弹出的"CUDA out of memory"错误提示可能是每个AI开发者最不愿看到的画面。选择一张合适的推理显卡&#xff0c;往往意…...

AI编程助手Trae使用详解

Trae是字节跳动推出的AI原生集成开发环境&#xff0c;支持macOS和Windows双平台&#xff0c;内置Claude-3.5、GPT-4o、DeepSeek等顶级AI模型&#xff0c;具备代码补全、智能问答等核心功能。相比传统编辑器&#xff0c;Trae的最大特点是深度集成了AI协作能力&#xff0c;可以实…...

从HC-SR04老用户视角,实测2020新版:盲区更小、功耗更低,但这两点不注意容易翻车

HC-SR04新版深度评测&#xff1a;老用户必看的5个升级细节与3个隐藏陷阱 第一次拿到2020版HC-SR04时&#xff0c;我差点以为发错了货——外观几乎和老版本一模一样&#xff0c;连螺丝孔位都分毫不差。但当我用示波器捕捉到仅2.1mA的工作电流时&#xff0c;才确信这确实是用上了…...