当前位置: 首页 > news >正文

【优选算法】—— 字符串匹配算法

在本期的字符串匹配算法中,我将给大家带来常见的两种经典的示例:

  • 1、暴力匹配(BF)算法
  • 2、KMP算法

目录

(一)暴力匹配(BF)算法

1、思想

2、演示

3、代码展示

(二)KMP算法

1、思想

2、演示

1️⃣ BF和KMP的区别

 2️⃣  K 的值求解

3️⃣ 求next数组的练习

3、代码展示

4、next数组的优化

(三)总结


(一)暴力匹配(BF)算法

1、思想

BF 算法,即 暴力 (Brute Force) 算法 ,是普通的模式匹配算法, BF 算法的思想:
  1. 就是将目标串S的第一个字符与模式串T 的第一个字符进行匹配,若相等,则继续比较S的第二个字符和 T的第二个字符;
  2. 若不相等,则比较S的第二个字符和 T的第一个字符,依次比较下去,直到得出最后的匹配结果。BF算法是一种蛮力算法。

2、演示

大家看到上诉这段话时肯定是晦涩难懂的,需要例子支持
下面我们就通过例子来解释这个问题:
  • 假定我们给出字符串ababcabcdabcde作为主串, 然后给出子串:abcd”;
  • 现在我们需要查找子串是否在主串中出现,出现返回主串中的第一个匹配的下标,失败返回-1 

  •  只要在匹配的过程当中,匹配失败,那么:i回退到刚刚位置的下一个,j回退到0下标重新开始

3、代码展示

int BF(char *str,char *sub) //str:主串 sub:子串
{assert(str != NULL && sub != NULL);if(str == NULL || sub == NULL){return -1;}int i = 0;int j = 0;int strLen = strlen(str);int subLen = strlen(sub);while(i < strLen && j < subLen){if(str[i] == sub[j]){i++;j++;}else{//回退i = i-j+1;j = 0;}}if(j >= subLen){return i-j;}return -1;
}
int main()
{printf("%d\n",BF("ababcabcdabcde","abcd"));printf("%d\n",BF("ababcabcdabcde","abcde"));printf("%d\n",BF("ababcabcdabcde","abcdef"));return 0;
}

时间复杂度分析:最坏为 O(m*n); m 是主串长度, n 是子串长度

(二)KMP算法

1、思想

KMP 算法是一种改进的字符串匹配算法,由 D.E.Knuth J.H.Morris V.R.Pratt 提出的,因此人们称它为克努特 莫里斯— 普拉特操作(简称 KMP 算法)。 KMP 算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是通过一个next() 函数实现, 函数 本身包含了模式串的局部匹配信息。 KMP 算法的 时间复杂度 O(m+n) [1]   。 来自 ------- 百度百科。

2、演示

1️⃣ BF和KMP的区别

区别 KMP BF 唯一不一样的地方在,我主串的 i 并不会回退,并且 j 也不会移动到 0 号位置

 首先举例,为什么主串不回退?

 的回退位置

💨 针对上述这样的情况,我们就需要引出next数组

KMP 的精髓就是 next 数组:也就是用 next[j] = k;来表示,不同的  j 来对应一个 K 值, 这个 K 就是你将来要移动的 j 要移动的位置。

 2️⃣  K 的值求解

  • 1、规则:找到匹配成功部分的两个相等的真子串(不包含本身),一个以下标 0 字符开始,另一个以 j-1 下标字符结尾。
  • 2、不管什么数据 next[0] = -1;next[1] = 0;在这里,我们以下标来开始,而说到的第几个第几个是从 1 开始

3️⃣ 求next数组的练习

练习 1: 举例对于”ababcabcdabcde”, 求其的 next 数组?

 到这里大家对如何求next数组应该问题不大了,接下来的问题就是,已知next[i] = k;怎么求next[i+1] = ?

如果我们能够通过 next[i] 的值 , 通过一系列转换得到 next[i+1] 得值,那么我们就能够实现这部分。
那该怎么做呢?

  1. 首先假设: next[i] = k 成立,那么,就有这个式子成立: P0...Pk-1 = Px...Pi-1;得到: P0...Pk-1 = Pi-k..Pi-1;
  2. 到这一步:我们再假设如果 Pk = Pi;我们可以得到 P0...Pk = Pi-k..Pi;那这个就是 next[i+1] = k+1;

 那么: Pk != Pi 呢?

 

3、代码展示

void GetNext(int *next,const char *sub)
{int lensub = strlen(sub);next[0] = -1;next[1] = 0;int i = 2;//下一项int k = 0;//前一项的Kwhile(i < lensub)//next数组还没有遍历完{if((k == -1) || sub[k] == sub[i-1]){next[i] = k+1;i++;k++;//k = k+1???//下一个K的值新的K值}else{k = next[k];}}
}int KMP(const char *s,const char *sub,int pos)
{int i = pos;int j = 0;int lens = strlen(s);int lensub = strlen(sub);int *next = (int *)malloc(lensub*sizeof(int));//和子串一样长assert(next != NULL);GetNext(next,sub);while(i < lens && j < lensub){if((j == -1) || (s[i] == sub[j])){i++;j++;}else{j = next[j];}}free(next);if(j >= lensub){return i-j;}else{return -1;}
}int main()
{char *str = "ababcabcdabcde";char *sub = "abcd";printf("%d\n",KMP(str,sub,0));return 0;
}

4、next数组的优化

next 数组的优化,即如何得到 nextval 数组:有如下串:
  1. aaaaaaaab;
  2. next 数组是-1,0,1,2,3,4,5,6,7
nextval 是:-1, -1, -1, -1, -1, -1, -1, -1, 7
💨  为什么出现修正后的数组,假设在 5 号处失败了,那退一步还是 a,还是相等,接着退还是 a
练习
模式串 t=‘abcaabbcabcaabdab’ ,该模式串的 next 数组的值为( D ) , nextval 数组的值为 ( F
A 0 1 1 1 2 2 1 1 1 2 3 4 5 6 7 1 2
B 0 1 1 1 2 1 2 1 1 2 3 4 5 6 1 1 2
C 0 1 1 1 0 0 1 3 1 0 1 1 0 0 7 0 1
D 0 1 1 1 2 2 3 1 1 2 3 4 5 6 7 1 2
E 0 1 1 0 0 1 1 1 0 1 1 0 0 1 7 0 1
F 0 1 1 0 2 1 3 1 0 1 1 0 2 1 7 0 1


(三)总结

BF(Brute Force)和KMP(Knuth-Morris-Pratt)算法是两种字符串匹配算法,它们的主要区别在于匹配过程中的策略和效率

  1. BF算法:

    • BF算法是一种简单直接的字符串匹配算法,也被称为朴素算法。
    • 它的思想是从主串中的每个位置开始,逐个比较主串和模式串的字符,直到找到匹配或遍历完所有可能位置。
    • 当字符不匹配时,BF算法通过移动主串指针,重新从下一个位置开始匹配。
    • BF算法的时间复杂度为O(m*n),其中m为主串长度,n为模式串长度,最坏情况下需要遍历所有可能的匹配位置。
    • 由于BF算法每次只移动一位,对于大规模文本匹配效率较低。
  2. KMP算法:

    • KMP算法是一种高效的字符串匹配算法,通过利用已知信息减少不必要的字符比较次数。
    • 它利用模式串自身的特性,在匹配过程中跳过一部分已经匹配的字符,从而提高匹配效率。
    • KMP算法包括两个主要步骤:构建最长公共前后缀数组(next数组)和匹配过程。
    • 最长公共前后缀数组(next数组)记录了模式串中对于每个位置,匹配失败时应该跳过的字符数。
    • 在匹配过程中,当字符不匹配时,KMP算法通过查询next数组获取跳跃位置,而不是重新从头开始比较。
    • KMP算法的时间复杂度为O(m+n),其中m为主串长度,n为模式串长度,通过next数组的优化,可以在匹配过程中跳过一定数量的比较,从而提高效率。

以下是关于上述两种算法的小结:

  1. 总结起来,BF算法是一种简单直接的字符串匹配算法,逐个比较字符并逐位移动,效率较低;
  2. 而KMP算法是一种高效的字符串匹配算法,通过构建最长公共前后缀数组和跳跃匹配位置,减少不必要的字符比较次数,提高匹配效率。
  3. 因此,在大规模文本匹配的应用中,KMP算法通常比BF算法更加高效。

相关文章:

【优选算法】—— 字符串匹配算法

在本期的字符串匹配算法中&#xff0c;我将给大家带来常见的两种经典的示例&#xff1a; 1、暴力匹配&#xff08;BF&#xff09;算法 2、KMP算法 目录 &#xff08;一&#xff09;暴力匹配&#xff08;BF&#xff09;算法 1、思想 2、演示 3、代码展示 &#xff08;二&…...

Docker容器:docker consul的注册与发现及consul-template守护进程

文章目录 一.docker consul的注册与发现介绍1.什么是服务注册与发现2.什么是consul3.docker consul的应用场景4.consul提供的一些关键特性5.数据流向 二.consul部署1.consul服务器&#xff08;192.168.198.12&#xff09;&#xff08;1&#xff09;建立 Consul 服务启动consul后…...

Blazor 依赖注入妙用:巧设回调

文章目录 前言依赖注入特性需求解决方案示意图 前言 依赖注入我之前写过一篇文章&#xff0c;没看过的可以看看这个。 C# Blazor 学习笔记(10):依赖注入 依赖注入特性 只能Razor组件中注入所有Razor组件在作用域注入的都是同一个依赖。作用域可以看看我之前的文章。 需求 …...

Python 基础 -- Tutorial(三)

7、输入和输出 有几种方法可以表示程序的输出;数据可以以人类可读的形式打印出来&#xff0c;或者写入文件以备将来使用。本章将讨论其中的一些可能性。 7.1 更花哨的输出格式 到目前为止&#xff0c;我们已经遇到了两种写值的方法:表达式语句和print()函数。(第三种方法是使…...

基于STM32的四旋翼无人机项目(二):MPU6050姿态解算(含上位机3D姿态显示教学)

前言&#xff1a;本文为手把手教学飞控核心知识点之一的姿态解算——MPU6050 姿态解算&#xff08;飞控专栏第2篇&#xff09;。项目中飞行器使用 MPU6050 传感器对飞行器的姿态进行解算&#xff08;四元数方法&#xff09;&#xff0c;搭配设计的卡尔曼滤波器与一阶低通滤波器…...

微信小程序开发教学系列(1)- 开发入门

第一章&#xff1a;微信小程序简介与入门 1.1 简介 微信小程序是一种基于微信平台的应用程序&#xff0c;可以在微信内直接使用&#xff0c;无需下载和安装。它具有小巧、高效、便捷的特点&#xff0c;可以满足用户在微信中获取信息、使用服务的需求。 微信小程序采用前端技…...

Nginx虚拟主机(server块)部署Vue项目

需求 配置虚拟主机&#xff0c;实现一个Nginx运行多个服务。 实现 使用Server块。不同的端口号&#xff0c;表示不同的服务&#xff1b;同时在配置中指定&#xff0c;Vue安装包所在的位置。 配置 Vue项目&#xff0c;放在 html/test 目录下。 config中的配置如下&#xf…...

JAVA开发环境接口swagger-ui使用总结

一、前言 swagger-ui是java开发中生产api说明文档的插件&#xff0c;这是后端工程师和前端工程师联调接口的桥梁。生成的文档就减少了很多没必要的沟通提高开发和测试效率。 二、 swagger-ui的使用 1、引入maven依赖 <dependency><groupId>io.springfox</grou…...

mongodb 数据库管理(数据库、集合、文档)

目录 一、数据库操作 1、创建数据库 2、删除数据库 二、集合操作 1、创建集合 2、删除集合 三、文档操作 1、创建文档 2、 插入文档 3、查看文档 4、更新文档 1&#xff09;update() 方法 2&#xff09;replace() 方法 一、数据库操作 1、创建数据库 创建数据库…...

分布式与集群的定义及异同

分布式与集群的定义及异同 分布式定义优点不足 集群优点不足 异同 分布式 定义 分布式是指将一个系统或应用程序分散到多个计算机或服务器上进行处理和管理的技术。它是指多个系统协同合作完成一个特定任务的系统。例如&#xff0c;可以将一个大业务拆分成多个子业务&#xf…...

电脑端teams一直在线小程序,简单好用易上手

居家办公的你&#xff0c;会不会想要摸鱼&#xff01;&#xff01;会不会想要下楼拿快递&#xff01;&#xff01;会不会想要出去下馆子&#xff01;&#xff01;&#xff01;然而&#xff0c;teams的5分钟不操作电脑状态就变为离开大大的阻挡了你幸福生活的脚步&#xff01;&a…...

YOLOv5算法改进(4)— 添加CA注意力机制

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。注意力机制是近年来深度学习领域内的研究热点&#xff0c;可以帮助模型更好地关注重要的特征&#xff0c;从而提高模型的性能。在许多视觉任务中&#xff0c;输入数据通常由多个通道组成&#xff0c;例如图像中的RGB通道或…...

无涯教程-PHP - XML GET

XML Get已用于从xml文件获取节点值。以下示例显示了如何从xml获取数据。 Note.xml 是xml文件&#xff0c;可以通过php文件访问。 <SUBJECT><COURSE>Android</COURSE><COUNTRY>India</COUNTRY><COMPANY>LearnFk</COMPANY><PRICE…...

Spark Standalone环境搭建及测试

&#x1f947;&#x1f947;【大数据学习记录篇】-持续更新中~&#x1f947;&#x1f947; 篇一&#xff1a;Linux系统下配置java环境 篇二&#xff1a;hadoop伪分布式搭建&#xff08;超详细&#xff09; 篇三&#xff1a;hadoop完全分布式集群搭建&#xff08;超详细&#xf…...

【PHP】流程控制-ifswitchforwhiledo-whilecontinuebreak

文章目录 流程控制顺序结构分支结构if分支switch分支 循环结构for循环while循环do-while循环continue和break 流程控制 顺序结构&#xff1a;代码从上往下&#xff0c;顺序执行。&#xff08;代码执行的最基本结构&#xff09; 分支结构&#xff1a;给定一个条件&#xff0c;…...

Pytorch-day04-模型构建-checkpoint

PyTorch 模型构建 1、GPU配置2、数据预处理3、划分训练集、验证集、测试集4、选择模型5、设定损失函数&优化方法6、模型效果评估 #导入常用包 import os import numpy as np import torch from torch.utils.data import Dataset, DataLoader from torchvision.transfor…...

使用Xshell7控制多台服务同时安装ZK最新版集群服务

一: 环境准备: 主机名称 主机IP 节点 (集群内通讯端口|选举leader|cline端提供服务)端口 docker0 192.168.1.100 node-0 2888 | 3888 | 2181 docker1 192.168.1.101 node-1 2888 | 388…...

python numpy array dtype和astype类型转换的区别

Python3 本身对整数的支持做了提升&#xff0c;可以支持无限长度的整数&#xff1a;比如&#xff1a; b 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffPython的模块numpy array定义的数组在windows和MACOS上默认长度是…...

浮动属性样式

&#x1f353;浮动属性 属性名称中文注释备注float设置盒子浮动left左浮动&#xff0c;right右浮动&#xff0c;none不浮动clear清除浮动left清除左浮动&#xff0c;right清除右浮动&#xff0c;both左右浮动都清除&#xff08;注意&#xff1a;clear清除浮动一般只有作用在块…...

keepalived双机热备 (四十五)

一、概述 Keepalived 是一个基于 VRRP 协议来实现的 LVS 服务高可用方案&#xff0c;可以解决静态路由出现的单点故障问题。 原理 在一个 LVS 服务集群中通常有主服务器&#xff08;MASTER&#xff09;和备份服务器&#xff08;BACKUP&#xff09;两种角色的服务器…...

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径

目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试

作者&#xff1a;Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位&#xff1a;中南大学地球科学与信息物理学院论文标题&#xff1a;BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接&#xff1a;https://arxiv.…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)

服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...

2021-03-15 iview一些问题

1.iview 在使用tree组件时&#xff0c;发现没有set类的方法&#xff0c;只有get&#xff0c;那么要改变tree值&#xff0c;只能遍历treeData&#xff0c;递归修改treeData的checked&#xff0c;发现无法更改&#xff0c;原因在于check模式下&#xff0c;子元素的勾选状态跟父节…...

【算法训练营Day07】字符串part1

文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接&#xff1a;344. 反转字符串 双指针法&#xff0c;两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)

要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况&#xff0c;可以通过以下几种方式模拟或触发&#xff1a; 1. 增加CPU负载 运行大量计算密集型任务&#xff0c;例如&#xff1a; 使用多线程循环执行复杂计算&#xff08;如数学运算、加密解密等&#xff09;。运行图…...

Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)

参考官方文档&#xff1a;https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java&#xff08;供 Kotlin 使用&#xff09; 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...

管理学院权限管理系统开发总结

文章目录 &#x1f393; 管理学院权限管理系统开发总结 - 现代化Web应用实践之路&#x1f4dd; 项目概述&#x1f3d7;️ 技术架构设计后端技术栈前端技术栈 &#x1f4a1; 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 &#x1f5c4;️ 数据库设…...