KMP匹配算法

news2024/11/25 6:28:53

目录

  • 一、暴力匹配法
    • 动画演示
    • 代码实现
  • 二、KMP算法的概念
  • 三、KMP算法的应用
    • 题目
    • 代码实现


一、暴力匹配法

动画演示

暴力遍历法
时间复杂度为: O ( m ∗ n ) O(m * n) O(mn)

代码实现

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;

int find(string& s1, string& s2)
{
	int n = s1.size();
	int m = s2.size();
	for (int i = 0; i <= n - m; ++i)
	{
		int cp = i, j = 0;
		while (cp < n && s1[cp] == s2[j]) cp++, j++;
		if (j == m - 1) return cp;
	}
	return -1;
}
int main()
{
	string txt = "ABCDABCDABDE";
	string pat = "ABCDABD";
	cout << find(txt, pat) << endl;
	
	return 0;
}

二、KMP算法的概念

K M P KMP KMP 算法,通常用于在一个 文本字符串 S S S 中查找一个 匹配串 P P P出现位置出现次数

KMP算法

KMP算法首先对模式串进行预处理,计算出Next数组。Next数组的每个元素表示当前位置之前的子串中,最长的相等的前缀和后缀的长度。然后,在匹配过程中,使用Next数组来指导模式串的移动。

当模式串与文本串的某个字符不匹配时,根据Next数组的值确定模式串的移动位置,而不是从头开始逐个字符地比较。通过合理地利用Next数组,KMP算法能够有效地避免不必要的比较操作,从而提高匹配的效率。

难点在于通过预处理得到Next数组 及其 回退处理的操作

相关求解视频:

【搬运】油管阿三哥讲KMP查找算法,中英文字幕,人工翻译,简单易懂


三、KMP算法的应用

题目

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

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

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

输入格式:
第一行,输入整数 n n n,表示字符串 P P P 的长度。

第二行,输入字符串 P P P

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

第四行,输入字符串 S S S

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

数据范围:
1 ≤ n ≤ 1 0 5 1≤n≤10^5 1n105
1 ≤ m ≤ 1 0 6 1≤m≤10^6 1m106

输入样例:

3
aba
5
ababa

输出样例:

0 2

代码实现

const int N = 1e5 + 10, M = 1e6 + 10;

int ne[N];
char s[M];
char p[N];

int main()
{
	cin.tie(nullptr);
	int n, m;
	cin >> n;
	for (int i = 0; i < n; ++i) cin >> p[i];
	cin >> m;
	for (int i = 0; i < m; ++i) cin >> s[i];
	
	// 创建Next数组
    // i:当前试图进行匹配的S串字符,j是模板串当前试图与S串i位置进行匹配的字符
    // j:表示已匹配的长度,一直都在尝试让j位和i位进行匹配,退无可退,无需再退。
    // i:是从1开始的,因为ne[0]=0,表示第1个不匹配,只能重头开始,不用算
	for (int i = 1, j = 0; i < n; i++) // j - 前缀末,i - 后缀末
	{
		while (j && p[i] != p[j]) j = ne[j - 1];
		if (p[i] == p[j]) j++;
		ne[i] = j;
	}

	for (int i = 0, j = 0; i < m; i++)
	{
		while (j && s[i] != p[j]) j = ne[j - 1];
		if (s[i] == p[j]) j++;
		if (j && j == n)
		{
			printf("%d ", i + 1 - n);
			j = ne[j - 1];
		}
	}
	return 0;
}

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

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

相关文章

Revit API:ErrorHandling

前言 本文介绍 Revit 的错误处理机制。 内容 程序员对错误处理的定义和理解 程序的错误处理机制可以分为两种类型&#xff1a;错误返回码和异常捕捉。 错误返回码是指在程序中遇到错误时&#xff0c;通过函数返回值来表明错误的类型和信息。错误返回码可以在程序中被预测和…

分段存储管理方式

目录 一、分段存储管理方式的引入的需求: 1.方便编程 2.信息共享 3.信息保护 4.动态增长 5.动态链接 二、分段系统的基本原理 1.分段 2.段表 3.地址变换机构 4.分页与分段的主要区别 三、信息共享 四、段页式存储管理方式 1.基本原理 2.地址变换过程 分段与分页…

Spring实现IOC和DI入门案例(XML版)

文章目录 1 IOC入门案例(XML版)1.1 思路分析1.2 代码实现步骤1:创建Maven项目步骤2:添加Spring的依赖jar包步骤3:添加案例中需要的类步骤4:添加spring配置文件步骤5:在配置文件中完成bean的配置步骤6:获取IOC容器步骤7:从容器中获取对象进行方法调用步骤8:运行程序 2 DI入门案例…

AltTab for Mac 像Windows一样的窗口快速切换工具

AltTab for Mac AltTab for Mac 是一款非常好用的窗口快速切换工具&#xff0c;AltTab将Windows的 “Alt-Tab” 窗口切换器的功能引入到了macOS。可以让您更快的在各个程序之间自由切换&#xff0c;大大提高您的工作效率。 AltTab for Mac下载 AltTab for Mac AltTab for Ma…

哈工大软件过程与工具作业2

云原生技术云原生技术 哈尔滨工业大学 计算机科学与技术学院/国家示范性软件学院 2022年秋季学期 《软件过程与工具》课程 作业报告 作业 2&#xff1a;需求分析UML建模 姓名 学号 联系方式 石卓凡 120L021011 944613709qq.com/18974330318 目 录 1 需求概述...........…

Vue3——简易版个人空间(上半部分)

创建项目 使用vue 的图形化界面创建一个新的vue3项目如下图所示 装两个新的插件——router和vuex插件 该过程的可能有点久&#xff0c;需要耐心等待。 再装一些需要的依赖 需要用到的依赖: boostrap和poperjs/core&#xff08;bootstrap是提供给不会做美工的程序员的一个新的…

物联网|uart串口相关寄存器|波特率设置及计算|发送处理代码|串口接收中断处理函数|物联网之蓝牙4.0 BLE基础-学习笔记(7)

文章目录 13 uart串口基础开发基本电路图&#xff1a;实验相关寄存器波特率设置及计算计算过程&#xff1a;设置中断发送处理代码串口接收中断处理函数main.c 13 uart串口基础开发 基本电路图&#xff1a; 实验相关寄存器 相关寄存器UxCSR、UxCSR、UxGCR、UxBUF、UxBAUD、CLK…

大厂设计师青睐的十大设计网站

设计绝对是薪酬差距最大的职业之一&#xff0c;有些人年薪100万&#xff0c;有些人月薪3000。 你有没有想过普通人和高薪设计师之间的差距在哪里&#xff1f; 在这篇文章中&#xff0c;我们将解密大厂设计师青睐的十大设计网站。让我们看看&#xff01; 1.即时设计 即时设计…

眺望高阶智能驾驶的远方,北醒驶入新“平台”

从4月到5月&#xff0c;关于2023上海国际车展的话题热度始终不减。 这次车展既让外界感受到了车企们的“卷”&#xff0c;也把智能汽车产业发展的蓝图更加清晰地呈现了出来——智能汽车正在进入产业布局的关键期&#xff0c;产业链上下游发展不断提速。 作为推动汽车产业的“…

基于边缘的图像分割

文章目录 基于边缘的图像分割基本原理常用的算法实现步骤示例代码结论 基于边缘的图像分割 基于边缘的图像分割是数字图像处理中常用的一种方法&#xff0c;它通过检测图像中的边缘信息来实现图像的分割。边缘通常代表着图像中不同区域之间的边界或目标的轮廓&#xff0c;因此…

Java 8 腰斩,Java 17 暴涨 430% (文末惊喜福利)

文末送出惊喜赠书福利一份&#xff0c;绝对high到爆&#xff01; 预约视频号&#xff1a;《Java核心技术》新书发布会暨"Java核心技术大会2023"启动仪式 New Relic 最新发布了一份 “2023 年 Java 生态系统状况报告”&#xff0c;旨在提供有关当今 Java 生态系统状态…

51单片机(十六)AD/DA

❤️ 专栏简介&#xff1a;本专栏记录了从零学习单片机的过程&#xff0c;其中包括51单片机和STM32单片机两部分&#xff1b;建议先学习51单片机&#xff0c;其是STM32等高级单片机的基础&#xff1b;这样再学习STM32时才能融会贯通。 ☀️ 专栏适用人群 &#xff1a;适用于想要…

罗马斗兽场在古罗马时期为什么这么流行,它对罗马有何影响?

在古罗马时期&#xff0c;斗兽场可谓是当时的一大热门娱乐场所。为何斗兽场如此受欢迎&#xff0c;它又如何影响了罗马社会呢&#xff1f; 斗兽场是古罗马人民的一种独特的娱乐形式。无论贵族、平民还是奴隶&#xff0c;他们都喜欢观看这种刺激的竞技。 有人认为&#xff0c;斗…

弹性盒子的属性

display&#xff1a;指定元素使用弹性盒子布局&#xff0c;属性值为 flex 或 inline-flex。 flex-direction&#xff1a;指定弹性盒子主轴的方向&#xff0c;属性值可以是 row&#xff08;默认值&#xff0c;主轴为水平方向&#xff09;、row-reverse&#xff08;主轴为水平方…

第11章:约束

一、数据完整性与约束的分类 1.为什么需要约束constraint SQL以约束方式对表数据进行额外的条件限制。 为了保证数据的完整性&#xff0c;SQL对表数据进行条件限制 ①实体完整性&#xff1a;同一个表&#xff0c;不能存在两条相同无法区分的记录 ②域完整性&#xff1a;年…

【数据结构】入门及时间空间复杂度的介绍

&#x1f331;博客主页&#xff1a;大寄一场. &#x1f331;系列专栏&#xff1a;数据结构与算法 &#x1f618;博客制作不易欢迎各位&#x1f44d;点赞⭐收藏➕关注 目录 前言 1.什么是数据结构&#xff1f; 2.什么是算法&#xff1f; 3.数据结构和算法的重要性 4.常见的数…

【杂记】Rest风格

文章目录 1.什么是Rest&#xff1f;2.URI URL URN3.什么是Restful架构风格4.状态转换 1.什么是Rest&#xff1f; Rest是一种软件架构的风格。 英文名称&#xff1a;REpresentational State Transfer&#xff08;表现层状态转移&#xff09; 加上主语&#xff1a;Resource Repr…

Linux网络基础-3

在上一篇网络基础的博客当中&#xff0c;我们对应用层协议--HTTP协议进行了详解&#xff0c;接下来我们对传输层协议进行详解 目录 1.传输层协议 2.UDP协议 2.1协议内容 2.2协议格式 2.3协议特性 3.TCP协议 3.1协议内容 3.2协议格式 3.3协议特性 3.3.1三次握手建立连…

Bootstrap开发之——Bootstrap安装及使用(02)

一 概述 Bootstrap下载npm安装bootstrap并使用(vue中使用)bootstrap通过本地lib导入并使用(html)bootstrap通过cdn导入并使用(html) 二 Bootstrap下载 2.1 Bootstrap下载(v3.x版本为例) 在Bootstrap中文官网&#xff0c;点击顶部的入门标签&#xff0c;在如下图页面点击下载…

Linux——对权限的理解

文章目录 总述Linux权限的概念Linux 权限管理Linux对文件访问者的分类文件类型和访问权限a.文件类型b.基本权限文件权限修改的相关方法 其他问题在首次创建时文件的权限属性是固定的吗&#xff1f;目录的权限粘滞位 总述 本篇博客将主要讲解linux系统中权限的概念&#xff0c;权…