暴力匹配字符串的升级版算法 —— Kmp算法

在这里插入图片描述

文章目录

  • 一、Kmp算法是什么?
  • 二、算法分析
    • 1.构建next数组
    • 2.匹配主串
  • 三、完整代码


一、Kmp算法是什么?

简单来说,KMP(Knuth-Morris-Pratt)算法主要用于解决字符串匹配问题。也就是当你有一个主串(text)和一个模式串(pattern)时,KMP算法可以在主串中快速找到模式串的出现位置。其核心思想是利用已经部分匹配的信息来避免不必要的匹配尝试。
相对于我们最开始使用的暴力匹配两个字符串是否相等的时间复杂度大大降低。、
上面说道 KMP 算法主要是通过消除主串指针的回溯来提高匹配的效率的,那么,它是则呢样来消除回溯的呢?就是因为它提取并运用了加速匹配的信息!

二、算法分析

1.构建next数组

KMP需要next数组的辅助,那么它是如何来生成的呢?可以采用递推的方式进行快速求解,利用已经掌握的信息来避免重复的运算。
其中next数组是使用匹配串进行构建出来的,它通过使用一个preCommonLen的变量来记录这个字符串的共同公共前缀。
在这里插入图片描述
在这里插入图片描述
根据上面得出,这个next就是记录了存放这个数组前后具有相同的前后缀

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在生成呢next[ ]的过程中,如果遇到不一样的字符该怎么办呢?

​ 其实可以找出不一样的字符的前一位,例如上面的 C与B不相同,那么就找最近的A重新比较,也就是左边字符串的后缀A

在这里插入图片描述
因为这里A的下标为 1 ,跳过一位,那么就是从B开始判断; 则右边的从B开始进行重新比较

所以蓝色箭头的值与黄色箭头的值一样,所以重新有共同的字串,则黄色箭头的值为 2

就这样我们就完成了Kmp算法的核心:构建next[ ]数组

 // todo 构建next数组private static int[] buildedString(String patternString/*匹配串,不是主串*/,int[] arrayPatternNext) {int prefix_len=0;// 共同前缀int i=1;//从下标1开始,因为第0位前缀为0char[] chars=patternString.toCharArray();while (i<patternString.length()){if (chars[prefix_len]==chars[i]){prefix_len+=1;arrayPatternNext[i]=prefix_len;i+=1;}else {if (prefix_len==0){//没有公共前缀arrayPatternNext[i]=0;i+=1;}else prefix_len=arrayPatternNext[prefix_len-1];// 不相等且有公共前缀,那么需要根据next数组来更新公共前缀}}return arrayPatternNext;}

2.匹配主串

步骤:

1 i 下标是不会回溯的,只会往前;

2 如果两个字符串的相同下标的比较字符相等的话,就进行向下移动;

3 当匹配中有不一样的字符时,就会去找next【】数组的相同子串后缀下标的值,并进行跳过多少位。
在这里插入图片描述

例如这里跳过了 2 位,所以子串下标 j = 2 ,指在了【0,1,2】第三号元素进行下一次的重新匹配,完美的跳过了上一次的重复字符,避免了回溯带来的时间损耗,这个就是KMP算法的魅力了。
在这里插入图片描述


// 字符串的匹配private static int getCommonString(String a/*主串*/, String patternString, int[] arrayPatternNext) {int i=0;int j=0;while (i<a.length()){// 主串的下标一直往前走,则时间复杂度为线性if (a.charAt(i)==patternString.charAt(j)){i+=1;j+=1;}else if (j>0){//因为当前面不匹配的时候,这个匹配串的下标就需要根据next数组作出调整j=arrayPatternNext[j-1];}else i+=1; //不相等,字串下标也没有动,主串下标就往前走if (j==patternString.length()-1){ //模式串的j到达了末尾commonLen=i-j+1;// 直接计算长度并返回break;}}return commonLen;}

三、完整代码

import java.io.*;
import java.util.Arrays;
import java.util.Scanner;public class Kmp {static  int commonLen=0;public static void main(String[] args) throws IOException {BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));System.out.println("输入主串:");String a=bufferedReader.readLine();System.out.println("输入匹配串");String patternString=bufferedReader.readLine();if (a.length()<patternString.length()) System.out.println("主串需要大于等于匹配串");else {int[] arrayPatternNext=new int[patternString.length()];Arrays.fill(arrayPatternNext,0);arrayPatternNext=buildedString(patternString,arrayPatternNext);System.out.println(getCommonString(a,patternString,arrayPatternNext)==0?"主串没有找到匹配串":"主串存在该匹配字串");}}private static int getCommonString(String a, String patternString, int[] arrayPatternNext) {int i=0;int j=0;while (i<a.length()){// 主串的下标一直往前走,则时间复杂度为线性if (a.charAt(i)==patternString.charAt(j)){i+=1;j+=1;}else if (j>0){//因为当前面不匹配的时候,这个匹配串的下标就需要根据next数组作出调整j=arrayPatternNext[j-1];}else i+=1; //不相等,字串下标也没有动,主串下标就往前走if (j==patternString.length()-1){commonLen=i-j+1;break;}}return commonLen;}// todo 构建next数组private static int[] buildedString(String patternString,int[] arrayPatternNext) {int prefix_len=0;// 共同前缀int i=1;char[] chars=patternString.toCharArray();while (i<patternString.length()){if (chars[prefix_len]==chars[i]){prefix_len+=1;arrayPatternNext[i]=prefix_len;i+=1;}else {if (prefix_len==0){//没有公共前缀arrayPatternNext[i]=0;i+=1;}else prefix_len=arrayPatternNext[prefix_len-1];}}return arrayPatternNext;}
}

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

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

相关文章

OceanBase 轻量级数仓关键技术解读

码到三十五 &#xff1a; 个人主页 为了更好地聚合和治理跨域数据&#xff0c;帮助企业用较低的成本快速聚合分析&#xff0c;快速决策&#xff0c;不断的让企业积累的数据产生价值&#xff0c;从全域海量数据抓取&#xff0c;高性能流批处理&#xff0c;元数据血缘治理等等方面…

AI-数学-高中52-离散型随机变量概念及其分布列、两点分布

原作者视频&#xff1a;【随机变量】【一数辞典】2离散型随机变量及其分布列_哔哩哔哩_bilibili 离散型随机变量分布列&#xff1a;X表示离散型随机变量可能在取值&#xff0c;P:对应分布在概率&#xff0c;P括号里X1表示事件的名称。 示例&#xff1a;

QT:QT窗口(一)

文章目录 菜单栏创建菜单栏在菜单栏中添加菜单创建菜单项添加分割线 工具栏创建工具栏设置停靠位置创建工具栏的同时指定停靠位置使用QToolBar类提供的setAllowedAreas函数来设置停靠位置 设置浮动属性设置移动属性 状态栏状态栏的创建在状态栏中显示实时消息在状态栏中显示永久…

AI人才争夺战,华尔街入局:豪掷百万美元年薪抢人

继硅谷之后&#xff0c;华尔街也入局**“AI人才争夺大战”**。 他们的目标非常明确——抢的就是高精尖的AI专家。 △图源&#xff1a;Business Insider 现在这条“街”上&#xff0c;不论是银行、对冲基金还是私募股权公司都已纷纷下场&#xff0c;可谓是豪掷千金&#xff0c…

选择深度学习框架:TensorFlow 2 vs PyTorch

TensorFlow 2 vs PyTorch 选择深度学习框架&#xff1a;TensorFlow 2 vs PyTorchTensorFlow 2概述TensorFlow 2的优点TensorFlow 2的缺点 PyTorch概述PyTorch的优点PyTorch的缺点 选择建议对于选择困难症的人&#xff0c;我给你们的答案——PyTorch选择理由&#xff1a;结论&am…

【LinuxC语言】setitimer与getitimer函数

文章目录 前言一、setitimer() 函数二、getitimer() 函数三、示例代码总结 前言 在Linux系统下&#xff0c;编写程序时经常需要使用定时器来实现一些定时任务、超时处理等功能。setitimer() 和 getitimer() 函数是两个用于操作定时器的重要函数。它们可以帮助我们设置定时器的…

[华为OD]C卷 给定一个数组,数组中的每个元素代表该位置的海拔高度 山脉的个数 200

题目&#xff1a; 给定一个数组&#xff0c;数组中的每个元素代表该位置的海拔高度。0表示平地&#xff0c;&#xff1e;1时表示属于某个 山峰&#xff0c;山峰的定义为当某个位置的左右海拔均小于自己的海拔时&#xff0c;该位置为山峰。数组起始位 置计算时可只满足一边…

SpringBoot自定义定时任务

通常&#xff0c;在我们的项目中需要定时给前台发送一些提示性消息或者我们想要的定时信息&#xff0c;这个时候就需要使用定时任务来实现这一功能&#xff0c;实现也很简单&#xff0c;接下来具体来看看吧~ 简单定时任务 首先&#xff0c;你需要在你的启动类上加上开启定时任…

YOLOv5改进之bifpn

目录 一、原理 二、代码 三、在YOLOv5中的应用 一、原理 论文链接:

[Linux][网络][TCP][一][TCP基础][TCP报头]详细讲解

目录 1.TCP头部格式2.TCP协议的特点3.TCP如何封装与分用4.通过序列号和确认应答号提高可靠性1.32位序列号2.32位确认应答号3.保证可靠性4.为什么序列号和确认应答号是单独的字段 5.窗口大小1.TCP的发送和接收缓冲区2.窗口大小 6.连接管理机制 1.TCP头部格式 TCP全称为"传输…

Ubuntu20安装torch1.13和pytorch_geometric2.3.0(对应cuda11.6)

在torch下载页面搜索1.13https://pytorch.org/get-started/previous-versions/&#xff0c;wheel安装方式&#xff08;激活conda虚拟环境&#xff09; pip install torch1.13.0cu116 torchvision0.14.0cu116 torchaudio0.13.0 --extra-index-url https://download.pytorch.org…

【Trick】conda安装python依赖时出现429 Client Error

起因 我在根据yml文件安装依赖和创建虚拟环境时&#xff0c;出现报错&#xff0c;主要报错信息为以下两点&#xff1a; 【1】Collecting package metadata (repodata.json): failed 【2】requests.exceptions.HTTPError: 429 Client Error: Too Many Requests for url: https…

C++笔记打卡第25天(机房预约系统)

1.机房预约系统需求 1.1 系统简介 学校有几个规格不同的机房&#xff0c;使用时经常会出现重复现象&#xff0c;现开发一套机房预约系统&#xff0c;解决这一问题。 1.2 身份简介 分别有三种身份使用该程序&#xff1a; 学生代表&#xff1a;申请试用机房教师&#xff1a;…

深入理解网络原理3----TCP核心特性介绍(上)【面试高频考点】

文章目录 前言TCP协议段格式一、确认应答【保证可靠性传输的机制】二、超时重传【保证可靠性传输的机制】三、连接管理机制【保证可靠性传输的机制】3.1建立连接&#xff08;TCP三次握手&#xff09;---经典面试题3.2断开连接&#xff08;四次挥手&#xff09;3.3TCP状态转换 四…

车载电子电器架构 —— 如何理解和使用Update bit

车载电子电器架构 —— 如何理解和使用Update bit 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不…

RabbitMQ(Docker 单机部署)

序言 本文给大家介绍如何使用 Docker 单机部署 RabbitMQ 并与 SpringBoot 整合使用。 一、部署流程 拉取镜像 docker pull rabbitmq:3-management镜像拉取成功之后使用下面命令启动 rabbitmq 容器 docker run \# 指定用户名-e RABBITMQ_DEFAULT_USERusername \# 指定密码-e R…

C++学习--点滴记录011

11函数提高 11.1 函数默认参数 在C中&#xff0c;函数的形参列表中的形参可以有默认值 语法&#xff1a; 返回值类型 函数名 &#xff08;参数 默认值&#xff09;{} 示例&#xff1a; #include <iostream> using namespace std;int func(int a, int b 10, int c …

IoTDB 入门教程 基础篇③——基于Linux系统快速安装启动和上手

文章目录 一、前文二、下载三、解压四、上传五、启动六、执行七、停止八、参考 一、前文 IoTDB入门教程——导读 二、下载 下载二进制可运行程序&#xff1a;https://dlcdn.apache.org/iotdb/1.3.1/apache-iotdb-1.3.1-all-bin.zip 历史版本下载&#xff1a;https://archive.…

springboot 集成 flowable

随着企业对于业务流程管理需求的增加&#xff0c;流程引擎在企业信息化建设中的作用越来越重要。Flowable是一个开源的轻量级业务流程管理&#xff08;BPM&#xff09;和工作流引擎&#xff0c;它支持BPMN 2.0标准。 Flowable的一些特点&#xff1a; 安装集成&#xff1a;Flow…

每日一题(AL001):A+B Format--字符串处理

找输出的顺序很重要&#xff1a; #include<bits/stdc.h> using namespace std; int main(){int a,b;cin>>a>>b;int sumab;if(sum0) cout<<0;bool ftrue;vector<char> v;if(sum<0) {ffalse; sum-sum;}while(sum>0){char cstatic_cast<c…