KMP字符串

试题传送门:831. KMP字符串 

给定一个字符串 S,以及一个模式串 P,所有字符串中只包含大小写英文字母以及阿拉伯数字。

模式串 P 在字符串 S 中多次作为子串出现。

求出模式串 P 在字符串 S 中所有出现的位置的起始下标。

输入格式

第一行输入整数 N,表示字符串 P 的长度。

第二行输入字符串 P。

第三行输入整数 M,表示字符串 S 的长度。

第四行输入字符串 S。

输出格式

共一行,输出所有出现位置的起始下标(下标从 0 开始计数),整数之间用空格隔开。

数据范围

1≤N≤1e5
1≤M≤1e6

输入样例:
3
aba
5
ababa
输出样例:
0 2

试题解析:

题意解释:

在一个字符串S中,寻找字串P,输出P在S中对应的下标。

关于KMP算法:

首先,介绍一下KMP算法与暴力匹配算法的区别。

  • 当我们要进行类似本题的字符串匹配操作时,如果使用暴力匹配做法,将P的第一个元素从S的第一个元素开始匹配,如果匹配失败,则将P的第一个元素从S的第二个元素开始匹配,依次类推,这样花费的时间是很长的,时间复杂度为O(M*N)。
  • 我们怎么通过一种方式,来进行更快的匹配呢?
    已知每一次匹配失败,p串就移动到s串的下一位开始匹配,那么我们是否可以找到相同的前缀和后缀,选择最长的一端开始匹配呢?
  • 前缀:指除了最后一个字符以外,一个字符串的全部头部组合。
    后缀:指除了第一个字符以外,一个字符串的所有尾部组合。
    下面来举个例子:

    当我们在匹配失败时,可以通过寻找最长前后缀的方式,更新p在s的下一次查找下标,以达到更快的速度。
  • next数组(本题为ne数组)的作用便是记录下在某一下标下,p[1...j]串中前后缀相同的最大长度,并将长度记录在下标为j的数组中。
    下面举一个例子方便理解:
    Pabcab
    下标j12345
    ne[j]00012
  • 我们如何在代码上求出next数组呢?
    可以通过模板串p进行自我匹配,求出p[1...j]串中前后缀相同的最大长度,并将长度记录在下标为j的数组中。
    在本题中:i表示匹配成功时对应的下标,j表示自我匹配时p数组中的下标。
    注意细节:在计算next数组的值时,当元素个数为1时,ne[1]绝对为0。
    //j表示匹配成功的长度,i表示p数组中的下标
    //因为p数组下标从1开始,ne[1]一定为0,所以i从2开始
    for (int i = 2, j = 0; i <= n; i++) {while (j && p[i] != p[j + 1]) j = ne[j]; //若不匹配,更新j到ne[j]if (p[i] == p[j + 1]) j++; //成功即匹配下一个ne[i] = j; //保存next数组
    }

  • 在进行字符串匹配时,其原理与ne数组的求取相似。
    值得注意的一点是:由于ne数组的值已经求完,现在进行的是S串与P串的匹配操作,那我们的S串就应该从第一个元素开始匹配,当j==n则是匹配成功,输出对应下标并进行下一次的匹配,切记,匹配勿忘ne数组!
    匹配代码如下:
    //j表示匹配成功的长度,从长度为0开始匹配
    for (int i = 1, j = 0; i <= m; i++) {while (j && s[i] != p[j + 1]) j = ne[j]; //若不匹配,更新j到ne[j]if (s[i] == p[j + 1]) j++; //成功即匹配下一个if (j == n) {printf("%d ", i - j); //输出对应下标j = ne[j]; //更新j,继续进行匹配}
    }
题解代码:

最后,我们来给出最终的题解代码。

#include<iostream>
using namespace std;
constexpr int N = 100010, M = 1000010;
char p[N], s[M];
int ne[N];
int main() {int n, m;//字符串下标均从1开始cin >> n >> p + 1 >> m >> s + 1;//j表示匹配成功的长度,i表示p数组中的下标//因为p数组下标从1开始,ne[1]一定为0,所以i从2开始for (int i = 2, j = 0; i <= n; i++) {while (j && p[i] != p[j + 1]) j = ne[j]; //若不匹配,更新j到ne[j]if (p[i] == p[j + 1]) j++; //成功即匹配下一个ne[i] = j; //保存next数组}//j表示匹配成功的长度,从长度为0开始匹配for (int i = 1, j = 0; i <= m; i++) {while (j && s[i] != p[j + 1]) j = ne[j]; //若不匹配,更新j到ne[j]if (s[i] == p[j + 1]) j++; //成功即匹配下一个if (j == n) {printf("%d ", i - j); //输出对应下标j = ne[j]; //更新j,继续进行匹配}}return 0;
}

 

 

        

 

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

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

相关文章

Azure Machine Learning - Azure AI 搜索中的索引器

在 Azure AI 搜索中&#xff0c;搜索索引是可搜索的内容&#xff0c;可供搜索引擎用于索引编制、全文搜索和筛选后查询。 索引由架构定义并保存到搜索服务中&#xff0c;第二步是数据导入。 除了在主数据存储中&#xff0c;此内容也存在于搜索服务中&#xff0c;这是在新式应用…

由11月27日滴滴崩溃到近两个月国内互联网产品接二连三崩溃引发的感想

文章目录 知乎文分析微信聊天截图微信公众号 滴滴技术 发文k8s 官方文档滴滴官方微博账号 近两个月国内互联网产品“崩溃”事件2023-10-23 语雀崩溃2023-11-12 阿里云崩溃2023-11-27 滴滴崩溃2023-12-03 腾讯视频崩溃总结 我的感想 知乎文分析 最近连续加班&#xff0c;打车较…

todesk连接ubuntu显示当前系统并无桌面环境,或无显示器,无法显示远程桌面,您需要自行安装X11桌面环境,或者使用终端文件功能

ToDesk远程遇到的问题如上图&#xff0c;换向日葵直接黑屏&#xff1b; 问题原因 截止发文时间&#xff0c;Todesk只支持X11协议&#xff0c;没有适配最新的Wayland协议&#xff0c;所以我们需要把窗口系统调整为X11才可以。 解决方法 修改配置文件&#xff0c;关闭wayland su…

【模电】基本共射放大电路的工作原理及波形分析

基本共射放大电路的工作原理及波形分析 在上图所示的基本放大电路中&#xff0c;静态时的 I B Q I\tiny BQ IBQ、 I C Q I\tiny CQ ICQ、 U C E Q U\tiny CEQ UCEQ如下图( b )、( c )中虚线所标注。 &#xff08; a &#xff09; u i 的波形&#xff08; b &#xff09; i B …

LeetCode:1038. 从二叉搜索树到更大和树(反向中序遍历 C++、Java)

目录 1038. 从二叉搜索树到更大和树 题目描述&#xff1a; 实现代码与解析&#xff1a; dfs 原理思路&#xff1a; 1038. 从二叉搜索树到更大和树 题目描述&#xff1a; 给定一个二叉搜索树 root (BST)&#xff0c;请将它的每个节点的值替换成树中大于或者等于该节点值的所…

JDK8新特性——Stream流

文章目录 一、Stream流体验二、Stream流的创建三、Stream流中间方法四、Stream流终究方法 Stream流&#xff08;也叫Stream API&#xff09;。它是从JDK8以后才有的一个新特性&#xff0c;是专业用于对集合或者数组进行便捷操作的 一、Stream流体验 需求&#xff1a;有一个Lis…

linux远程桌面管理工具(xrdp)、向日葵

Windows远程桌面 linux远程桌面 使用向日葵远程桌面&#xff08;手机端同理&#xff09; Windows远程桌面 微软自带Remote Desktop Connection Manager &#xff08;RDCMan&#xff09;远程控制管理软件介绍 远程桌面连接管理器 v2.93 linux远程桌面 Windows远程桌面Ubunt…

JVM 运行时内存(三)

Java 堆从 GC 的角度还可以细分为: 新生代(Eden 区、From Survivor 区和 To Survivor 区)和老年代。 1. 新生代 是用来存放新生的对象。一般占据堆的 1/3 空间。由于频繁创建对象&#xff0c;所以新生代会频繁触发MinorGC 进行垃圾回收。新生代又分为 Eden 区、ServivorFrom、…

Android Framework 电池提醒相关Dialog熄屏消失的问题

记录一下花了三四天干一天就能完成的需求的傻事。 说在前头&#xff0c;这篇文章记录了电池提醒dialog相关&#xff0c;弹出dialog且熄屏再亮屏dialog不会消失的代码&#xff0c;这篇废话比较多&#xff0c;看正常代码直接跳到代码3。 故事背景 需求要求添加非法电池的弹窗&a…

[多线程]阻塞队列和生产者消费者模型

目录 1.阻塞队列 1.1引言 1.2Java标准库中的阻塞队列 1.3自主通过Java代码实现一个阻塞队列(泛型实现) 2.生产者消费者模型 1.阻塞队列 1.1引言 阻塞队列是多线程部分一个重要的概念,它相比于一般队列,有两个特点: 1.线程是安全的 2.带有阻塞功能 1) 队列为空,出队列就会阻…

语义分割 DeepLab V1网络学习笔记 (附代码)

论文地址&#xff1a;https://arxiv.org/abs/1412.7062 代码地址&#xff1a;GitHub - TheLegendAli/DeepLab-Context 1.是什么&#xff1f; DeepLab V1是一种基于VGG模型的语义分割模型&#xff0c;它使用了空洞卷积和全连接条件随机&#xff08;CRF&#xff09;来提高分割…

JAVA-作业7-画一个笑脸

要求如题 代码如下&#xff1a; SmileFace01: import java.awt.Color; import java.awt.Graphics;import javax.swing.JPanel;public class SmileFace01 extends JPanel {Overrideprotected void paintComponent(Graphics g) {super.paintComponent(g);int width getWidth(…

代码随想录刷题题Day5

刷题的第五天&#xff0c;希望自己能够不断坚持下去&#xff0c;迎来蜕变。&#x1f600;&#x1f600;&#x1f600; 刷题语言&#xff1a;C / Python Day5 任务 ● 哈希表理论基础 ● 242.有效的字母异位词 ● 349. 两个数组的交集 ● 202. 快乐数 ● 1. 两数之和 1 哈希表理…

MT8390商显广告机主板_MTK联发科安卓主板方案开发

商显广告机采用MediaTek 联发科平台主板方案。安卓主板具有更高的性能、更丰富的接口、更多的存储空间以及更为便捷的网络连接方式&#xff0c;可以满足更为复杂的开发和应用需求使其应用领域更加多元化&#xff0c;被广泛应用于各行各业。 商显广告机主板基于联发科MT8390八核…

智能AI系统ChatGPT网站系统源码+Midjourney绘画+支持DALL-E3文生图,支持最新GPT-4-Turbo模型

一、AI创作系统 SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭建部署AI…

Ubuntu18.04安装Ipopt-3.12.8流程

本文主要介绍在Ubuntu18.04中安装Ipopt库的流程&#xff0c;及过程报错的解决方法&#xff0c;已经有很多关于Ipopt安装的博客&#xff0c;但经过我的测试&#xff0c;很多都失效了&#xff0c;经过探索&#xff0c;找到可流畅的安装Ipopt的方法&#xff0c;总结成本篇博客。 …

使用typescript搭建express

使用typescript搭建express 开始 为这个项目创建一个新的目录&#xff0c;使用下面的命令初始化项目并创建一个包。 NPM init -y初始化后&#xff0c;让我们安装必要的包 npm i express dotenv cors helmet body-parser 在express中配置typescript npm i -D typescript typ…

WordPress批量上传文章和自动发布文章的方法

专业介绍&#xff1a;WordPress批量上传文章技术解析 在现代数字时代&#xff0c;内容创作是网络存在的驱动力之一。对于博客作者、新闻编辑和内容管理员而言&#xff0c;高效地批量上传文章至WordPress平台是提高工作效率的一个关键方面。WordPress作为最受欢迎的内容管理系统…

【C语言】递归详解

目录 1.前言2. 递归的定义3. 递归的限制条件4. 递归举例4.1 求n的阶乘4.1.1 分析和代码实现4.1.2 画图演示 4.2 顺序打印一个整数的每一位4.2.1 分析和代码实现4.2.2 画图推演 4.3 求第n个斐波那契数 5. 递归与迭代5.1 迭代求第n个斐波那契数 1.前言 这次博客内容是与递归有关&…

迪文串口5使用查询方式发送数据

迪文屏串口5寄存器如下 发送数据我采用的不是中断&#xff0c;而是查询发送标志位实现的。 串口5不像串口2一样&#xff08;串口2可以位寻址&#xff0c;串口5不行&#xff09;&#xff0c;所以如果采用查询模式&#xff0c;需要判断寄存器的数据&#xff0c;我的写法比较简单…