KMP字符串 (简单清晰/Java)

news2024/11/25 2:07:15

Kmp算法

解决问题:
字符串匹配问题
怎么解决?
前缀表+next[]数组
#分析
先看暴力做法:

  1. 两层for循环,一层遍历文本串,一层遍历模式串(子串)
  2. 对应的每个字符进行匹配,匹配成功就 i+ +j+ + 继续匹配
  3. 匹配不成功则break,退出循环.
    那这样做时间复杂度为O(m*n)

再看Kmp做法
1.先将模式串和文本串一 一匹配,遇到冲突,即匹配不成功时,需要退一位继续匹配。
那这一位怎么退?
借助前缀表!

2.需要求模式串的前缀表,怎么求?
先引入一个ne
数组,next数组的求算相当于双指针算法
从左至右开始遍历,计算前缀和后缀最长相等的长度
最后,得到的是一个升序序列,序列中的值便是退一位的索引,即ne[j]。

3.借助ne[]数组,进行退一位处理。
如果当前冲突了,那我们就找到模式串冲突位置j的前一位即ne[j]。
这里的话p数组做了往前移动一位处理,那这样对应的每个j冲突的退一位索引直接就是ne[j]。

4.退一位处理后,会确保ne[j]的前缀和文本串冲突位置前的串的后缀相同。
那这样就开始在 j=ne[j] 的下一位开始与冲突位置进行匹配。

如果匹配不到,则继续退一位处理,继续匹配。
如果匹配得到,则记录i的位置,注意i保留的是匹配成功的最后一位。

所以,答案下标等于 i-n+1 ,但是这里写法是从下标1开始,所以 i-n+1-1=i - n

分析一下KMP算法的时间复杂度:
先for循环遍历一下,移动j的位置,最多前移m 次、后移每次,总计为2*m

所以Kmp的时间复杂度O(2*m)=O(m)

过程模拟图

分析图

在这里插入图片描述

前缀表计算展开图
注意:
前缀是不含尾字母的所有子串
后缀是不含首字母的所有子串
找到最长相等的前缀和后缀长度即可

图1

在这里插入图片描述

图二

在这里插入图片描述

图三

在这里插入图片描述

代码

import java.io.*;
public class Main{
	public static void main(String []args) throws NumberFormatException, IOException {
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
		int N=100010,M=1000010;
		int n =  Integer.parseInt(in.readLine());
		String P = in.readLine();
		char []p = new char[N];
		//输入的数组下标从1开始
		for(int i=1;i<=n;i++) {
			p[i]=P.charAt(i-1);//将字符串P的每个字符存入字符数组
		}
		int m = Integer.parseInt(in.readLine()); 
		String S = in.readLine();
		char []s = new char[M];
		for(int i=1;i<=m;i++) {
			s[i] = S.charAt(i-1);//将字符串S的每个字符存入字符数组
		}
		
		int ne[]=new int [N];
		
		//前缀表
		//i=1时,ne[1]=0;所以从i=2开始即可。
		for(int i=2,j=0;i<=n;i++) {
		    //j从0开始,进入循环会加上1,主要是为了做退格处理。
		
			while(j>0&&p[i]!=p[j+1])j=ne[j];
			//那么我们去找他的前一位来进行匹配,即往前退一格,再比较。
			
			if(p[i]==p[j+1])j++;//匹配相等的话,则j++
			
			ne[i]=j;//更新ne数组i的值为j
		}
		
		for(int i=1,j=0;i<=m;i++) {
		    
		    //j+1是退格定位到j之后的位置再继续比较。
			while(j>0&&s[i]!=p[j+1])j=ne[j];
			
			if(s[i]==p[j+1])j++;//匹配成功,则i、j继续往下走
			
			if(j==n) {
			    //i最后记录的是字符串匹配成功的最后一位,需要i-n+1.
			    //但是这里的下标从1开始,需要减1,所以是i-n。
				
			out.write((i-n)+" ");
		
		//保存当前满足条件的ne[j]的位置,接下来继续匹配可能会用到。
				j=ne[j];
			}
		
		}
		out.flush();
		out.close();
		in.close();		
	}
}

参考资源

理论:
https://b23.tv/BTna3qX
next[]
https://b23.tv/bI8oAJG

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

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

相关文章

【前端】求职必备知识点2-CSS:优先级、盒子模型、标准流、浮动流、定位流

文章目录 CSS优先级盒子模型标准流、浮动流、定位流标准流浮动流定位流 思维导图 CSS优先级 class类选择器&#xff0c;属性选择器&#xff0c;伪类 的权值为10元素选择器、伪元素选择器权值为1 属性选择器&#xff1a;如&#xff0c;将有title的元素变为红色。 [title] { co…

Python pygame(GUI编程)模块最完整教程(8)

上一篇文章&#xff1a; Python pygame(GUI编程)模块最完整教程&#xff08;7&#xff09;_Python-ZZY的博客-CSDN博客 总目录&#xff1a; README.md Python-ZZY/Python-Pygame最完整教程 - Gitee.com 23 进阶声音操作 参考资料&#xff1a; https://pyga.me/docs/ref/…

在编程下仰望

编程的尽头是数学 数学的尽头是物理 物理的尽头是哲学 哲学的尽头是耶稣 路漫漫其修远兮&#xff0c; 各位码农同仁 好自珍重

Kafka第一课概述与安装

生产经验 面试重点 Broker面试重点 代码,开发重点 67 章了解 如何记录行为数据 1. Kafka概述 1.产生原因 前端 传到日志 日志传到Flume 传到HADOOP 但是如果数据特比大&#xff0c;HADOOP就承受不住了 2.Kafka解决问题 控流消峰 Flume传给Kafka 存到Kafka Hadoop 从Kafka…

geoserver编辑样式 【开发工具QGis的初次使用】

geoserver编辑样式 开发工具配置中文语言 geoserver样式的更改 开发工具 链接: geoserver样式style的更改 链接: QGis开发工具的安装及使用 配置中文语言 setting > options > general > 中文 geoserver样式的更改 链接: geoserver样式style的更改 利用QGIs Q…

3DMAX动力学布料模拟插件DynamoCloth使用方法

3DMAX动力学布料模拟DynamoCloth是一个&#xff08;实时&#xff09;GPU加速的3ds Max Cloth动力学插件&#xff0c;与原生Cloth修改器相比&#xff0c;性能提高了10-100倍。 3DMAX动力学布料模拟是实时的&#xff0c;能够实现实时的自然互动&#xff0c;并将创作过程从试错转…

代码随想录算法训练营第十五天| 层序遍历(即广度优先搜索), 226.翻转二叉树,101. 对称二叉树

层序遍历(即广度优先搜索) 需要借用一个队列来实现&#xff0c;队列先进先出&#xff0c;符合一层一层遍历的逻辑&#xff0c;而用栈先进后出适合模拟深度优先遍历也就是递归的逻辑。 思路是先把根节点加入队列&#xff0c;然后在遍历下一层前&#xff0c;先将队列拥有的当前层…

LeetCode150道面试经典题--找出字符串中第一个匹配项的下标(简单)

1.题目 给你两个字符串 haystack 和 needle &#xff0c;请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标&#xff08;下标从 0 开始&#xff09;。如果 needle 不是 haystack 的一部分&#xff0c;则返回 -1 。 2.示例 3.思路 回溯算法&#xff1a;首先将…

【CSS3】CSS3 动画 ⑥ ( 动画属性示例 | 精灵图帧动画效果实现 )

文章目录 一、需求说明二、代码分析1、动画属性2、布局分析3、动画实现 三、完整代码示例 一、需求说明 给定一张精灵图 , 其中有多个 动画帧 对应的图片 , 下图的大小是 1600 x 100 像素 , 截图展示如下 : 实际图片 : 二、代码分析 1、动画属性 使用上图实现 逐帧动画 效果 …

智慧工地云平台源码

智慧工地可以实现对人员管理、施工进度、安全管理、材料管理、设备管理、环境监测等方面的实时监控和管理&#xff0c;提高施工效率和质量&#xff0c;降低安全风险和环境污染。在道路施工中&#xff0c;智慧工地可以实现对道路状况、交通流量、施工进度等方面的实时监控和管理…

Wlan——802.11协议物理层关键技术(OFDM、MIMO、BSS)和CSMA/CD机制的介绍

目录 802.11协议的发展 802.11协议物理层关键技术 信道捆绑技术 OFDM/OFDMA技术 Short-Gi短保护间隔技术 MIMO/MU-MIMO技术 QAM技术 BSS Color快速识别 802.11MAC层关键技术CSMA/CD机制 为什么无线提出了CSMA/CD机制 CSMA/CD的工作机制 CSMA/CD的工作原理 CSMA/CD…

matlab进行mex时出现 error LNK2019: 无法解析的外部符号

解决方法分成三个步骤&#xff1a; 1、直接在simulink模块运行出现错误&#xff0c;找不到该s函数&#xff1b; 2、需要确认安装了编译器。mex -setup 确认安装了编译器&#xff0c;再次mex xxx.c未解决&#xff1b; 3、再次查找资料发现可能编译器不知道具体的位置&#xff0c…

Java训练六

目录 一、除数不能为0 二、校验年龄格式 三、终端循环 四、 计算最大公约数 一、除数不能为0 使用静态变量、静态方法以及throws关键字&#xff0c;实现当两个数相除且除数为0时&#xff0c;程序会捕获并处理抛出的ArithmeticException异常&#xff08;算术异常&#xff09…

电脑合上盖子无线网络不会断开

控制面板\硬件和声音\电源选项\系统设置 最终选择不会采取任何操作 选择不会采取任何操作

学习C语言第三天 :关系操作符、逻辑操作符

1.关系操作符 C语言用于比较的表达式&#xff0c;称为“关系表达式”里面使用的运算符就称(relationalexpression)&#xff0c;为“关系运算符” (relationaloperator) &#xff0c;主要有下面6个。 > 大于运算符 < 小于运算符 > 大于等于运算符 < 小于等…

分布式 - 消息队列Kafka:Kafka生产者架构和配置参数

文章目录 1. kafka 生产者发送消息整体架构2. Kafka 生产者重要参数配置01. acks02. 消息传递时间03. linger.ms04. buffer.memory05. batch.size06. max.in.flight.requests.per.connection07. compression.type08. max.request.size09. receive.buffer.bytes和 send.buffer.b…

如何使用appuploader制作apple证书​

转载&#xff1a;如何使用appuploader制作apple证书​ 如何使用appuploader制作apple证书​ 一.证书管理​ 点击首页的证书管理 二.新建证书​ 点击“添加”&#xff0c;新建一个证书文件 免费账号制作证书只有7天有效期&#xff0c;没有推送消息功能&#xff0c;推送证书…

anaconda 基本指令

1.anaconda创建环境 例如我们创建一个名称为img2word&#xff0c;python版本为3.9的环境 conda create -n img2word python3.9在这个命令中&#xff1a; create 是告诉 Conda 你要创建一个新的环境。-n img2word 是设置新环境的名称为 img2word。python3.9 是告诉 Conda 在这…

PS AI版本安装教程

好久没写博客了&#xff0c;今天更新一下子吧&#xff01; 随着chatGPT的提出&#xff0c;各种软件逐渐开始镶嵌人工智能&#xff0c;为我们的生活带来了极大的便利&#xff01;话不多说&#xff0c;开始介绍今天的主角&#xff0c;PS的AI版本。 安装教程&#xff1a; 1.安装…

Linux学习之sed删除、追加、插入、更改、读写文件、下一行、打印、退出和seq命令

cat /etc/redhat-release看到操作系统是CentOS Linux release 7.6.1810&#xff0c;uname -r看到内核版本是3.10.0-957.el7.x86_64&#xff0c;sed --version可以看到sed版本是4.2.2。 echo a : 1 : good : g >> sed_daicpnrwq.txt echo b : 2 : well : w >> sed…