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];}}}}

之后如果有新的想法会及时补充,大家如果有不同见解欢迎评论区留言
在这里插入图片描述

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

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

相关文章

Spring Boot集成Swagger3.0,Knife4j导出文档

文章目录 Spring Boot集成Swagger3.0,Knife4j导出文档效果展示如何使用简要说明添加依赖添加配置类测试接口token配置位置 官网 说明情况 demo Spring Boot集成Swagger3.0,Knife4j导出文档 效果展示 如何使用 简要说明 Knife4j的前身是swagger-bootstrap-ui,前身swagger-boo…

Github-Copilot初体验-Pycharm插件的安装与测试

引言&#xff1a; 80%代码秒生成&#xff01;AI神器Copilot大升级 最近copilot又在众多独角兽公司的合力下&#xff0c;取得了重大升级。GitHub Copilot发布还不到两年&#xff0c; 就已经为100多万的开发者&#xff0c;编写了46%的代码&#xff0c;并提高了55%的编码速度。 …

springboot整合myabtis+mysql

一、pom.xml <!--mysql驱动包--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!--springboot与JDBC整合包--><dependency><groupId>org.springframework.b…

微信小程序实现日历功能、日历转换插件、calendar

文章目录 演示htmlJavaScript 演示 效果图 微信小程序实现交互 html <view wx:if"{{calendarArr.length}}"><view class"height_786 df_fdc_aic"><view class"grid_c7_104"><view class"font_weight_800 text_align…

Redis 数据库高可用

Redis 数据库的高可用 一.Redis 数据库的持久化 1.Redis 高可用概念 &#xff08;1&#xff09;在web服务器中&#xff0c;高可用是指服务器可以正常访问的时间&#xff0c;衡量的标准是在多长时间内可以提供正常服务&#xff08;99.9%、99.99%、99.999%等等&#xff09;。 …

【Golang 接口自动化02】使用标准库net/http发送Post请求

目录 写在前面 发送Post请求 示例代码 源码分析 Post请求参数解析 响应数据解析 验证 发送Json/XMl Json请求示例代码 xml请求示例代码 总结 资料获取方法 写在前面 上一篇我们介绍了使用 net/http 发送get请求&#xff0c;因为考虑到篇幅问题&#xff0c;把Post单…

Spring Boot 缓存 Cache 入门

Spring Boot 缓存 Cache 入门 1.概述 在系统访问量越来越大之后&#xff0c;往往最先出现瓶颈的往往是数据库。而为了减少数据库的压力&#xff0c;我们可以选择让产品砍掉消耗数据库性能的需求。 当然也可以引入缓存,在引入缓存之后&#xff0c;我们的读操作的代码&#xff…

介绍壹牛NFT数字艺术藏品数藏源码

这个版本新增了不少功能&#xff0c;也修复了一些地方。 1.平台新增用户找回密码功能 2.平台新增短信注册&#xff08;实名制功能&#xff09; 3.平台新增主图后台添加功能 4.平台修复相关问题&#xff0c;系统高效运行 5、H5端与APP端在新UI完美适配 6、加入宝盒功能&…

Java方法的使用(重点:形参和实参的关系、方法重载、递归)

目录 一、Java方法 * 有返回类型&#xff0c;在方法体里就一定要返回相应类型的数据。没有返回类型&#xff08;void&#xff09;&#xff0c;就不要返回&#xff01;&#xff01; * 方法没有声明一说。与C语言不同&#xff08;C语言是自顶向下读取代码&#xff09;&#…

基于SpringBoot+Vue的车辆充电桩管理系统设计与实现(源码+LW+部署文档等)

博主介绍&#xff1a; 大家好&#xff0c;我是一名在Java圈混迹十余年的程序员&#xff0c;精通Java编程语言&#xff0c;同时也熟练掌握微信小程序、Python和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架…

STM32 LWIP UDP 一对一 一对多发送

STM32 LWIP UDP通信 前言设置 IP 地址UDP函数配置实验结果单播发送&#xff0c;一对一发送广播发送&#xff0c;一对多发送 可能遇到的问题总结 前言 之前没有接触过网络的通信&#xff0c;工作需要 UDP 接收和发送通信&#xff0c;在网上没有找到一对一、一对多的相关例程&am…

什么是SVM算法?硬间隔和软间隔的分类问题

SVM全称是supported vector machine(支持向量机)&#xff0c;即寻找到一个超平面使样本分成两类&#xff0c;并且间隔最大。 SVM能够执行线性或⾮线性分类、回归&#xff0c;甚至是异常值检测任务。它是机器学习领域最受欢迎的模型之一。SVM特别适用于中小型复杂数据集的分类。…

CentOS 8 错误: Error setting up base repository

配置ip、掩码、网关、DNS VMware网关可通过如下查看 打开网络连接 配置镜像的地址 vault.centos.org/8.5.2111/BaseOS/x86_64/os/

通过String字符生成base64编码在生成图片

* base64转图片 //对字节数组字符串进行Base64解码并生成图片 * param base64str base64码 * return // param savePath 图片路径private static final String savePath"image_ver\\verifyCode"; 判断是否为base64编码 public static void mainDD…

【JavaEE初阶】Servlet (三)MessageWall

在我们之前博客中写到的留言墙页面,有很严重的问题:(留言墙博客) 如果刷新页面/关闭页面重开,之前输入的消息就不见了.如果一个机器上输入了数据,第二个机器上是看不到的. 针对以上问题,我们的解决思如如下: 让服务器来存储用户提交的数据,由服务器保存. 当有新的浏览器打开页…

基于java的坦克大战游戏的设计与实现--答辨PPT--【毕业论文】

文章目录 本系列校训毕设的技术铺垫PPT主体层次封面页目录页&#xff1a;设计工具与相关技术&#xff1a;系统分析总体设计&#xff1a;详细设计测试结论&#xff1a; 小技巧 本系列校训 互相伤害互相卷&#xff0c;玩命学习要你管&#xff0c;天生我才必有用&#xff0c;我命…

React(1)——快速入门

一、React背景简介 官网和资料 英文官网: https://reactjs.org/中文官网: 快速入门 – React (docschina.org) 3、如果JS基础忘了及时查看文档&#xff1a;JavaScript - 学习 Web 开发 |多核 (mozilla.org) JavaScript - 标签 - 汤姆大叔 - 博客园 (cnblogs.com) 4、React…

Neo4j图数据基本操作

Neo4j 文章目录 Neo4jCQL结点和关系增删改查匹配语句 根据标签匹配节点根据标签和属性匹配节点删除导入数据目前的问题菜谱解决的问题 命令行窗口 neo4j.bat console 导入rdf格式的文件 :GET /rdf/ping CALL n10s.graphconfig.init(); //初始化 call n10s.rdf.import.fetch(&q…

【软件测试】webdriver常用API演示(Java+IDEA+chrome浏览器)

1.元素定位方法 对象的定位应该是自动化测试的核心&#xff0c;要想操作一个对象&#xff0c;首先应该识别这个对象。一个对象就是一个人一样&#xff0c;他会有各种的特征&#xff08;属性&#xff09;&#xff0c;如比我们可以通过一个人的身份证号&#xff0c;姓名&#xf…

Redis 笔记,基本数据类型、持久化、主从、集群等等问题

标题 &#x1f600;&#x1f600;&#x1f600;创作不易&#xff0c;各位看官点赞收藏. 文章目录 标题Redis 基础笔记1、安装及环境搭建2、Redis 数据类型2.1、String2.2、List2.3、Hash2.4、Set2.5、Zset2.6、BitMap2.7、HyperLogLog2.8、Geospatial2.9、Stream 3、Redis 持久…