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

news2024/12/23 19:45:51

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

  • 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;//前一项的K
    while(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算法更加高效。

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

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

相关文章

nginx基于端口如何配置虚拟主机

在 Nginx 中配置基于端口的虚拟主机&#xff08;也称为服务器块&#xff09;与配置基于域名的虚拟主机类似&#xff0c;但是你需要指定监听的端口。以下是基于端口的虚拟主机配置示例&#xff1a; 假设我们要配置两个不同的虚拟主机&#xff0c;一个监听 8080 端口&#xff0c…

【自制C/C++小项目JuLongEditor】使用Windows控制台API来制作一个简单的文本编辑器

2023年8月22日&#xff0c;周二下午 昨天花了一个下午和晚上来制作的&#xff0c; 实现了一些基本的功能&#xff0c; 但由于代码只有130行&#xff0c;所以存在很多不足之处 GitHub&#xff1a;GitHub - JuLongZhiLu/JuLongEditor: C/C小项目&#xff0c;使用Windows控制台…

Hlang-从零开始编写一个vscode代码提示插件

文章目录 前言Hlang适配实现语法提示package.json配置编写提示语法配置语法高亮执行打包前言 通过一段时间的努力,Hlang是开发完毕了,但是我们还需要为它提供一个IDE。那么从零开发显然是不可取的,这会大大加大开发难度。但是我们可以基于vscode这个神奇的物质。所以我们只…

STM32驱动MAX30102心率血氧传感器(OLED显示)

STM32驱动MAX30102心率血氧传感器&#xff08;OLED显示&#xff09; 简介电气参数系统框图接线代码结果总结 简介 MAX30102是一个集成的脉搏血氧仪和心率监测仪模块。它包括内部led&#xff0c;光电探测器&#xff0c;光学元件&#xff0c;和低噪声电子与环境光排斥。MAX30102…

《三国》时期,谁才是优秀的项目经理

大家好&#xff0c;我是老原。 上一次细读三国&#xff0c;还是在老原高中的时候&#xff0c;当时只觉得他们神仙打架&#xff0c;谋略过人。 现在毕业也快10年&#xff0c;重读三国&#xff0c;我又有了新的一些发现——关于管理者。 金无赤足&#xff0c;人无完人。《三国…

stm32片内读写项目总结(多字节读写tongxindu)

1.flash操作驱动程序 a头文件 #ifndef FLASH_H #define FLASH_H #include “stm32f4xx.h” #define BOARD_NUM_ADDR 0x0800C000 #define STM32_FLASH_BASE 0x08000000 //STM32 FLASH的起始地址 #define FLASH_WAITETIME 50000 //FLASH等待超时时间 //FLASH 扇区的起始地址…

wazuh环境配置及漏洞复现

wazuh环境配置 案例复现 wazuh环境配置 1.进入官网下载OVA启动软件 Virtual Machine (OVA) - Installation alternatives (wazuh.com) 2.进入VMware像配置其他虚拟机一样进行配置即可 3.上面会有提示&#xff1a;账号为&#xff0c;wazuh-user&#xff1b;密码&#xff0c;wa…

Vue实现Excel表格中按钮增加小数位数,减少小数位数功能,多用于处理金融数据

效果图 <template><div><el-button click"increaseDecimals">A按钮</el-button><el-button click"roundNumber">B按钮</el-button><el-table :data"tableData" border><el-table-column v-for&q…

绿盾客户端字体库文件被加密了,预览不了

环境: 绿盾客户端7.0 Win10 专业版 问题描述: 绿盾客户端字体库文件被加密了,预览不了 预览不了 解决方案 1.打开控制台 2.进入规则中心 3.找到对应的操作员类型 4.选择自定义程序 5.右键新建程序,填最开始获得的程序名,可执行程序选择本地程序,我本地没有这个…

410随身WiFi刷完openwrt后作玩具nas/bt机

简单流程介绍&#xff1a;机子wifi模式改为客户端&#xff0c;添加ipv6&#xff0c;开放需要的端口&#xff0c;切换USB工作模式&#xff0c;挂载usb储存&#xff0c;安装qb/aria2之类软件 前提就是刷好openwrt了&#xff0c;教程话题里有 注意opemwrt的操作要及时保存并应用&a…

openGauss学习笔记-47 openGauss 高级数据管理-权限

文章目录 openGauss学习笔记-47 openGauss 高级数据管理-权限47.1 语法格式47.2 参数说明47.3 示例 openGauss学习笔记-47 openGauss 高级数据管理-权限 数据库对象创建后&#xff0c;进行对象创建的用户就是该对象的所有者。数据库安装后的默认情况下&#xff0c;未开启三权分…

5、Spring_DI注解开发

DI 注解开发 1.目前面临问题 建立 mapper public interface EmployeeMapper {void save(); }建立 mapper 实现类 Repository public class EmployeeMapperImpl implements EmployeeMapper {public void save(){System.out.println("保存员工信息");} }建立 service …

档案开发:增加查询和打卡按钮

档案开发&#xff1a;增加查询和打卡按钮 和单据开发的不同点 没有单据类型不是右击–>特性–>单据主表/单据子表&#xff0c;而是右击–>特性–>选择想要的接口访问器类型是NCVO不需要映射不是项目右键–>新建–>其他–>主子表单据结点&#xff0c;而是…

怕封店吗?来看看这份亚马逊测评宝典吧!

测评&#xff0c;一直是跨境电商亚马逊行业常谈论的话题&#xff0c;因为它是获取销量最快的方法之一&#xff0c;但对于测评&#xff0c;跨境电商亚马逊平台也是深恶痛绝&#xff0c;严厉打击测评行为&#xff0c;但不少的卖家仍旧喜欢铤而走险&#xff0c;做测评去提高店铺的…

Python打印七夕礼物

参考&#xff1a; python写七夕硬核礼物&#xff01; - 周旋机器视觉的文章 - 知乎 https://zhuanlan.zhihu.com/p/196451223 # -*- coding:utf-8 -*-# 导入opencv和openpyxl import openpyxl import cv2 as cv import numpy as np from openpyxl import load_workbook from o…

组织机构代码,注册号,纳税人识别号有什么区别?海关备案是什么?

组织机构代码&#xff0c;注册号&#xff0c;纳税人识别号有什么区别&#xff1f; 之前写过关于企业信用代码的文章&#xff0c;今天来讲一下企业的三证合一。三证合一指的是将识别号&#xff0c;注册号&#xff0c;组织机构代码三者共用一个号的说法。 但是&#xff0c;你看…

群英荟萃,决战渝城 | 第七届集创赛“加速科技杯”总决赛圆满落幕!

8月20-22日&#xff0c;第七届全国大学生集成电路创新创业大赛全国总决赛在重庆举办&#xff0c;“加速科技杯”中有26支优秀队伍从四百多支报名队伍中脱颖而出&#xff0c;获得总决赛各项大奖&#xff0c;取得了优异的成绩&#xff01;大赛同期举办的还有集创赛嘉年华、人才对…

python 项目打包器pyinstaller实践

在创建了独立应用&#xff08;自包含该应用的依赖包&#xff09;之后&#xff0c;还可以使用 PyInstaller 将 Python 程序生成可直接运行的程序&#xff0c;这个程序就可以被分发到对应的 Windows 或 Mac OS X 平台上运行。 安装 PyInstalle Python 默认并不包含 PyInstaller…

高隔音活动隔断墙是一种设计用于隔离声音、提供隐私和创建灵活空间的分隔墙

高隔音活动隔断墙是一种设计用于隔离声音、提供隐私和创建灵活空间的分隔墙。这种隔断墙通常在需要随时改变房间布局的场合&#xff0c;如酒店、会议中心、展览厅、办公室等地使用。 以下是有关高隔音活动隔断墙的一些重要特点和优势&#xff1a; 1. 隔音性能&#xff1a;高隔音…

Protobuf在IDEA中的插件安装教程

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…