KMP字符串匹配算法

本文用于记录个人算法竞赛学习,仅供参考

目录

一.KMP

二.next数组(前缀表)

三.具体实现模板

四.题解


先来看一个问题

28. 找出字符串中第一个匹配项的下标 - 力扣(LeetCode)

 对于这个问题,一般暴力做法是:遍历主串,以主串的每个元素为开头分别与模式串对比,遇到不匹配,主串走下一位,模式串重新开始 一 一对比,假设主串长度为n,模式串长度为m,那么时间复杂度是O(n * m)。

使用KMP解决这个问题时间复杂度只需要O(n + m)。

一.KMP

KMP主要用于字符串匹配的场景中,用于解决字符串匹配、重复子字符串等问题。

1.思想:当出现字符串不匹配时,可以通过一部分之已经匹配过的文本内容,利用这些信息避免从头再去匹配。

2.与暴力匹配的区别:KMP主串全程只遍历一遍,从不走回头路; 每次不匹配时模式串不需要回退到起点。

 能做到上述操作的主要原因是next数组的功能。

二.next数组(前缀表)

1.前缀表定义:记录下标i(包括i)之前的字符串中有多长的最长相同前后缀

前缀是不包含最后一个字符的连续子字符串;后缀是不包含第一个字符的连续子字符串。

2.前缀表的作用:用来模式串的回退,它记录了主串与模式串不匹配时模式串应该从哪里开始从新开始。

3.模拟匹配(这里是假设字符串下标是从1开始的,这样比较好实现):

3.求next数组

记录下标i(包括i)之前的字符串中有多长的最长相同前后缀,其实在实现next数组时,和主串与模式串匹配大差不差;

因为第一个位置既不能是前缀又不能是后缀,所以第一位(下标1)是0,直接跳过第一位从第二位开始求next数组;

现在可以将模式串看成是两个串,一个是从第二位开始的“主串”,一个是从第一位开始的“模式串”,为什么可以这样想,因为在第一位不存在前后缀,形成前后缀至少需要两个字符,这就形成了错位,后缀在后,前缀在前,求next数组就是求最长相同前后缀,这个过程相当于前缀与后缀在做匹配的过程。

三.具体实现模板

很多人都感觉KMP难以理解,是因为实现方式有很多种,都没有同一的实现方式,使很多人查找资料将多种解释混在一起就晕了。

这里先将实现细节约定熟成:

主串,模式串都是下标从1开始的字符串,这样好处理边界条件,next数组也是从下标1开始才有数据的。

//KMP伪代码

//s[] 是主串, p[] 是模式串, n 是主串长度, m 是模式串长度
//主串,模式串,next 数组都是下标从1开始才有 有效数据的

//求next数组
for (int i = 2, j = 0; i <= m; i++)
{
	while (j && p[i] != p[j + 1])
		j = next[j];
	if (p[i] == p[j + 1])
		j++;
	next[i] = j;
}

//匹配
for (int i = 1,j = 0; i <= n; i++)
{
	//回退
	while (j && s[i] != p[j + 1])
		j = next[j];
	if (s[i] == p[j + 1])
		j++;
	if (j == m)//模式串遍历完
	{
		j = next[j];
		//查找成功后的逻辑
	}
}

四.题解

所以开头的问题可以直接套用公式

class Solution {
public:
    int strStr(string haystack, string needle) {
        haystack.insert(0, 1, '0');
        needle.insert(0, 1, '0');
        int n = haystack.size() - 1;
        int m = needle.size() - 1;
        vector<int> next(m + 1);
        //求next数组
        for(int i = 2, j = 0; i <= m; i++)
        {
            while(j && needle[i] != needle[j + 1])
                j = next[j];
            if(needle[i] == needle[j + 1])
                j++;
            next[i] = j;
        }
        //匹配
        for(int i = 1, j = 0; i <= n; i++)
        {
            //回退
            while(j && haystack[i] != needle[j + 1])
                j = next[j];
            if(haystack[i] == needle[j + 1])
                j++;
            if(j == m)
            {
                return i - m;
            }
        }
        return -1;
    }
};

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

三、Java的流程控制

1、Java的顺序流程控制 程序由一系列语句组成。 Java虽然是一种面向对象的计算机语言,但是在一个局部,例如方法体内,快语句内仍然需要面向过程的程序设计和方法。 作为面向过程程序设计精华的结构化程序设计思想,仍然是面向对象程序设计方法的基石。 1)表达式语句 由运…

浪潮分布式存储AS13000G6-M36、NF5466M6硬盘背板改扩配参考

AS13000G6分布式存储机型描述 浪潮分布式存储AS13000G6-M36机型&#xff0c;实际就是NF5466M6加上分布式存储软件的一体机产品&#xff0c;而NF5468M6也就是NF5280M6的主板加4U机箱结构。 该机器最大的特点是在4U空间内可以配置36块3.5寸大盘&#xff0c;硬盘背板为3.5*12&…

B82793S0513N201 共模扼流圈滤波器电感 51uH 800mA

B82793S0513N201是一款由TDK(东电化)公司生产的数据线扼流圈&#xff0c;用于电信领域的xDSL变压器。 制造商: TDK 产品品种: 共模扼流圈/滤波器 RoHS: 详细信息 系列: B82793S 安装风格: PCB Mount 端接类型: SMD/SMT 通道数量: 1 Channel 电感: 51 uH 容差: 30 % 最大直流电…

护眼台灯什么品牌好?台灯目前口碑最好的护眼灯推荐

随着生活水平的提供&#xff0c;越来越多的人重视起自身健康问题&#xff0c;尤其是视力健康&#xff0c;因此都会选择一款好的护眼台灯。不过市面上的护眼台灯款式多得人数不清&#xff0c;其中还包括了很多劣质产品。 这类台灯往往采用劣质LED灯珠&#xff0c;这种灯珠对人体…

【5G 接口协议】CU与DU之间的F1协议介绍

博主未授权任何人或组织机构转载博主任何原创文章&#xff0c;感谢各位对原创的支持&#xff01; 博主链接 本人就职于国际知名终端厂商&#xff0c;负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作&#xff0c;目前牵头6G算力网络技术标准研究。 博客…

如何使用 Python 本地客户端操作读写云服务器 Redis 缓存数据库详细教程(更新中)

Redis 基本概述 Redis&#xff08;Remote Dictionary Server&#xff09;是一个开源的使用 ANSI C 语言编写的、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库&#xff0c;并提供多种语言的 API。它通常被称为数据结构服务器&#xff0c;因为值&#xff08;value…

【Leetcode】2810. 故障键盘

文章目录 题目思路代码复杂度分析时间复杂度空间复杂度 结果总结 题目 题目链接&#x1f517; 你的笔记本键盘存在故障&#xff0c;每当你在上面输入字符 ′ i ′ i ′i′ 时&#xff0c;它会反转你所写的字符串。而输入其他字符则可以正常工作。 给你一个下标从 0 0 0 开始…

.sdf和.msp文件读取

前言 .sdf和.msp文件都可以用来存储分子信息&#xff0c;.sdf文件可以用rdkit读取&#xff0c;.msp文件就只能当成文本文档读取了。 读取 rdkit安装 pip install rdkit .sdf读取 from rdkit import Chemsuppl_h Chem.SDMolSupplier(../data/HMDB/f_hmdb.sdf) # 得到一个迭…

【字节跳动笔试题汇总】 2024-03-31-字节跳动春招笔试题-三语言题解(CPP/Python/Java)

&#x1f36d; 大家好这里是KK爱Coding &#xff0c;一枚热爱算法的程序员 ✨ 本系列打算持续跟新字节跳动近期的春秋招笔试题汇总&#xff5e; &#x1f4bb; ACM银牌&#x1f948;| 多次AK大厂笔试 &#xff5c; 编程一对一辅导 &#x1f44f; 感谢大家的订阅➕ 和 喜欢&…

基于Python的口罩佩戴识别的设计与实现(UI界面+MySQL数据库+YOLOv5+训练数据集+开题报告+中期检查+论文)

本文旨在基于Python开发一种口罩佩戴识别系统&#xff0c;通过深度学习技术实现对口罩佩戴情况的准确检测。采用了YOLOv5系列目标检测算法作为基础模型&#xff0c;并结合迁移学习进行训练和优化。同时&#xff0c;为了提供更好的用户体验&#xff0c;本系统还设计了用户登录注…

“315晚会”中的“网络水军”是什么?

水军一词&#xff0c;源自网络用语&#xff0c;通常指的是一群在网络上被雇佣来进行特定活动的人群。他们的主要任务通常是在各种社交媒体平台、论坛或者评论区发表大量的帖子、评论或者回复&#xff0c;以此来达到某种特定的目的。这些目的可能包括提升某个产品、服务或者个人…

【机器学习300问】58、什么是词袋模型和N-gram模型?

词袋模型&#xff08;Bag of Words, BoW&#xff09;和N-gram模型主要用于早期的自然语言处理任务&#xff0c;上文中我介绍了机器是如何读懂文本的四个阶段&#xff0c;这篇文章带大家来看看在不同阶段中会用到的两个模型——词袋模型和N-gram模型。如果没有读过我之前的文章&…

纯小白蓝桥杯备赛笔记--DAY9(搜索)

文章目录 三道例题学会DFS剪枝什么是剪枝数字王国之军训排队--2942特殊的三角形--3008特殊的多边形--3075 DFS基础回溯简介回溯法模版例题N皇后--1508小朋友崇拜圈--182全球变暖--178 记忆化搜索简介斐波那契数列混境之地5-3820地宫取宝-216 三道例题学会DFS剪枝 什么是剪枝 …

云计算迎变局:阿里云、腾讯云“各有千秋”

毋庸置疑&#xff0c;无论在什么时候什么行业&#xff0c;低价策略都是一柄利器。比如&#xff0c;在电商行业&#xff0c;除了拼多多将低价策略贯彻到底之外&#xff0c;淘宝、京东也将性价比作为发力重点&#xff0c;并通过补贴、秒杀等方式&#xff0c;再度强调自身的“价格…

Pygame基础8-碰撞

Collisions 在Pygame中&#xff0c;我们使用矩形来移动物体&#xff0c;并且用矩形检测碰撞。 colliderect检测两个矩形是否碰撞&#xff0c;但是没法确定碰撞的方向。 Rect1.colliderect(Rect2) # collision -> return Ture # else -> return Falsecollidepoint可以…

数据结构——遍历二叉树和线索二叉树,树和森林

目录 1.遍历的算法实现 1.先序遍历 代码示例&#xff1a; 2.中序遍历 代码示例&#xff1a; 3.后序遍历 代码示例&#xff1a; 4.遍历算法的分析 2.遍历二叉树的非递归算法 1.中序遍历非递归算法 代码示例&#xff1a; 3.二叉树的层次遍历 代码示例&#xff1a; 4.二…

C#/.NET/.NET Core优秀项目和框架2024年3月简报

前言 公众号每月定期推广和分享的C#/.NET/.NET Core优秀项目和框架&#xff08;每周至少会推荐两个优秀的项目和框架当然节假日除外&#xff09;&#xff0c;公众号推文中有项目和框架的介绍、功能特点、使用方式以及部分功能截图等&#xff08;打不开或者打开GitHub很慢的同学…

BUUCTF [安洵杯 2019]吹着贝斯扫二维码 1

BUUCTF:https://buuoj.cn/challenges 题目描述&#xff1a; 得到的 flag 请包上 flag{} 提交。 密文&#xff1a; 下载附件解压&#xff0c;得到很多没有后缀的文件和一个ZIP压缩包。 解题思路&#xff1a; 1、首先&#xff0c;查看ZIP压缩包&#xff0c;发现有密码&#xf…

GreatSQL 优化技巧:将 MINUS 改写为标量子查询

GreatSQL 优化技巧&#xff1a;将 MINUS 改写为标量子查询 前言 minus 指令运用在两个 SQL 语句上&#xff0c;取两个语句查询结果集的差集。它先找出第一个 SQL 所产生的结果&#xff0c;然后看这些结果有没有在第二个 SQL 的结果中&#xff0c;如果在&#xff0c;那这些数据…

2024年山东临沂教育人才引进报名流程

2024年山东临沂教育人才引进报名流程