字符串匹配算法(BFKMP)

news2024/10/2 20:22:51

个人主页:平行线也会相交
欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 平行线也会相交 原创
收录于专栏【数据结构初阶(C实现)】
在这里插入图片描述

目录

  • 字符串匹配算法
    • BF算法
      • 代码实现
    • KMP算法
      • 代码实现
    • nextval数组改进

字符串匹配算法

在学习这个算法之前,我们先来看看什么时字符串匹配算法,简单来说有一个主串和一个子串,查找子串在主串的位置,然后返回这个位置的下标。
想要实现这个功能其实有很多方法,比较有名的算法有两种:一种是BF算法又称暴力算法,另一种就是KMF算法。

BF算法

BF算法:思想就是将目标串S的第一个字符与模式串T的第一个字符进行匹配,如果相等,则继续比较S的第二个字符和T的第二个字符;如果不相等,则比较S的第二个字符和T的第一个字符,依次比较下去,直到得出最后的酦醅结果。
举个例子:
在这里插入图片描述

代码实现

#define _CRT_SECURE_NO_WARNINGS 1
//BF算法

#include<assert.h>

#include<stdio.h>

//str为主串,sub为子串
int BF(char* str, char* sub)
{
	assert(str != NULL && sub != NULL);
	if (str == NULL || sub == NULL)
		return -1;
	int lenStr = strlen(str);
	int lenSub = strlen(sub);
	int i = 0;
	int j = 0;
	while (i < lenStr && j < lenSub)
	{
		if (str[i] == sub[j])
		{
			i++;
			j++;
		}
		else
		{
			i = i - j + 1;
			j = 0;
		}
	}
	if (j >= lenSub)//如果j>=lenSub说明子串遍历完成,即匹配成功,返回i的下标。
	{
		return i - j;
	}
	//不存在直接返回-1
	return -1;
}

int main()
{
	printf("%d\n", BF("ababcabcdabcde", "abcd"));
	printf("%d\n", BF("ababcabcdabcde", "abcdf"));
	printf("%d\n", BF("ababcabcdabcde", "ab"));
	return 0;
}

在这里插入图片描述

KMP算法

KMP算法就是对BF算法是一种对BF算法的改进,该算法核心就是可以利用匹配失败后的信息,尽量减少模式串与字串的匹配次数以到达快速匹配的目的(具体shi)。
KMP与BF算法的区别就是KMP算法主串的并不会回退;并且j不会移动到0号位置,而是移动到一个特定的位置。
我们直接来举个例子:

在这里插入图片描述

此时ij位置的字符不匹配了。此时i是不进行回溯的,而是要对j进行回溯,那么j应该回溯到哪个位置呢?
在这里插入图片描述
由于每个位置要回溯的位置可能不一样,所以就引出了next数组。即用next[j]=k来表示。不同的j对应一个K值。这个K就是将来j要进行回溯的位置。如上图我们求的是当j=5的时候,K的值就是2,即将来j要回溯到下标为2的位置。即next[5]=2;。再比如说,当j是4的时候,K的值就是1,即next[4]=1;
再来举个例子:

关于K值求取的规则如下:

1.找到匹配成功部分的两个相等的真串(不包含本身),一个以下标0开始,另一个j-1下标结束。
2.无论是什么数据,如果我们是从0开始计数(这里按照数组下标从0开始的习惯所以从0开始计数),那么next[0]=-1;next[1]=0;如果我们从1开始计数,那么next[0]=0;next[1]=1

来练习一下
"a b a b c a b c d a b c d e ",求其next数组
答案如下图:
在这里插入图片描述

代码实现

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<string.h>

void GetNext(char* sub, int* next, int lenSub)
{
	next[0] = -1;
	next[1] = 0;
	int i = 2;
	int k = 0;
	while (i < lenSub)
	{
		if (k == -1 || sub[i - 1] == sub[k])
		{
			next[i] = k + 1;
			i++;
			k++;
		}
		else
		{
			k = next[k];
		}
	}
}

int KMP(char* str, char* sub, int pos)
{
	assert(str != NULL && sub != NULL);
	int lenStr = strlen(str);
	int lenSub = strlen(sub);
	if (lenStr == 0 || lenSub == 0)
		return -1;
	if (pos < 0 || pos >= lenStr)
		return -1;

	int* next = (int*)malloc(sizeof(int) * lenSub);
	assert(next != NULL);

	GetNext(sub, next, lenSub);

	int i = pos;//遍历主串
	int j = 0;//遍历子串

	while (i < lenStr && j < lenSub)
	{
		if (j == -1 || str[i] == sub[j])
		{
			i++;
			j++;
		}
		else
		{
			j = next[j];
		}
	}
	if (j >= lenSub)
	{
		return i - j;
	}
	return -1;
}

int main()
{

	printf("%d\n", KMP("ababcabcdabcde", "abcd", 0));
	printf("%d\n", KMP("ababcabcdabcde", "abcdf", 0));
	printf("%d\n", KMP("ababcabcdabcde", "ab", 0));
	return 0;
}

在这里插入图片描述

nextval数组改进

下面来看nextval数组的求解规则

1.无论是什么数据,nextval[0]=-1;(这里还是默认数组的习惯从0开始计数)。如果是从1开始计数,则nextval[0]=0;
2.从第二位开始,我们用next[i]值对应的字符i值对应的字符进行比较。如果相等,则nextval[i]就等于next[i]值对应字符的nextval[i]值;如果不相等,则nextval[i]值就等于当前字符对应的next值

我们还是来进行举例:

求模式串"a b c a a b b c a b c a a b d a b"
在这里插入图片描述
下面来看详细过程:
个字符a对应的nextval[0]一定为-1(按照从0开始计数的话)。即nextval[0]=-1;
个字符b的next值即next[1]=0;所以第二个字符和下标为0的字符进行比较。发现不相等,所以nextval[1]=第二个字符所对应的next值,即nextval[1]=0;
个字符c的next值即next[2]=0;所以第三个字符和下标为0的字符进行比较。发现不相等,所以nextval[2]=第三个字符所对应的next值,即nextval[2]=0;
个字符a的next值即next[3]=0;所以第四个字符和下标为0的字符进行比较。发现相等了,所以nextval[3]=下标为0的字符所对应的nextval值,在这里就是nextval[3]=nextval[0]
个字符a的next值即next[4]=1;所以第五个字符a和下标为1的字符b进行比较。发现不相等,所以nextval[4]=当前字符(即指的是第五个字符)所对应的next值,所以最终nextval[4]=next[4]=1
依此类推进行分析,所以最终该串的nextval数组就如上图所示。

好了,以上就是关于字符串BF和KMP算法的一个记录。
就到这里吧,各位,再见啦!!!
在这里插入图片描述

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

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

相关文章

MySQL 库操作

目录 创建数据库 语法 案例 字符集和校验规则&#xff08;建数据库/建表用&#xff09; 查看系统默认字符集以及校验规则 db.opt 更改 查看数据库支持的字符集 查看数据库支持的字符集校验规则 校验规则对数据库的影响 排升序 操纵数据库 查看数据库 显示创建语…

[计算机图形学]几何:隐式显式表示(前瞻预习/复习回顾)

一、前言 本篇我们将开启GAMES101几何部分的讲解的第一讲解&#xff0c;也是几何的基本表示&#xff0c;现实中有非常多的几何&#xff0c;如布料&#xff0c;绝对光滑的曲面&#xff0c;水滴&#xff0c;毛发&#xff0c;微观的细胞等等非常复杂的几何&#xff0c;那么如何在…

十分钟在 macOS 快速搭建 Linux C/C++ 开发环境

有一个使用了 Epoll 的 C 项目&#xff0c;笔者平时用的 Linux 主力开发机不在身边&#xff0c;想在 macOS 上开发调试&#xff0c;但是没有 Linux 虚拟机。恰好&#xff0c;JetBrains CLion 的 Toolchains 配置除了使用本地环境&#xff0c;还支持 SSH、Docker。 笔者使用 CL…

Zabbix的介绍与部署

目录 zabbix zabbix简介 zabbix主要功能 zabbix主要特点 zabbix运行机制 zabbix架构 1.sever-client架构 2.sever-proxy-client架构 3.master-node-client架构 如何进行数据采集 zabbix工作原理 zabbix监控模式 安装zabbix5.0 部署zabbix服务端 web页面测试 部…

系统集成项目管理工程师 笔记(第二章:信息系统集成及服务管理)

文章目录2.3.1 ITIL与IT服务管理&#xff08;ITSM&#xff09; 117ITSM三个根本目标2.3.2 ITSS与信息技术服务 121ITSS的4个组成要素和5个生命周期2.3.3 信息系统审计 127信息系统审计是建立在以下 4 个理论基础之上的信息系统审计流程示意图审计步骤第2章 信息系统集成及服务管…

怎么设置动态壁纸?这样做就行!

案例&#xff1a;怎么设置动态壁纸 【朋友们&#xff0c;我的壁纸一直都是静态的&#xff0c;最近感觉有点审美疲劳了&#xff0c;想换些好看的动态壁纸&#xff0c;有朋友知道应该如何设置动态壁纸吗&#xff1f;】 经常使用电脑的朋友可能会觉得一直用同一张壁纸会感觉审美…

通过两阶段知识学习多种不利天气排除

论文&#xff1a;Learning Multiple Adverse Weather Removal via Two-stage Knowledge Learning and Multi-contrastive Regularization: Toward a Unified Model【通过两阶段知识学习多种不利天气排除】 论文下载地址&#xff1a;https://openaccess.thecvf.com/content/CVP…

过去的90天,ODC 发生了哪些新的改变?

欢迎访问 OceanBase 官网获取更多信息&#xff1a;https://www.oceanbase.com/ 关于作者 胡智娟 OceanBase 产品经理 主要负责 OceanBase 生态工具数据研发、迁移评估方向的产品工作&#xff0c;在蚂蚁集团有多年数据库管理实战经验&#xff0c;对日常研发及运维痛点有较深感悟…

个人-计算机操作系统第五章

第五章 虚拟存储器 一、章节练习 1.系统抖动是指( )。 A. 使用机器时&#xff0c;千万屏幕闪烁的现象 B. 刚被调出的页面又立刻被调入所形成的频繁调入调出现象 C. 系统盘不净&#xff0c;千万系统不稳定的现象 D. 由于内存分配不当&#xff0c;偶然造成内存不够…

史上最全的快速排序方法--Hoare快排 挖坑法快排 二路快排 三路快排 非递归快排

一.快速排序 1.基本介绍 快速排序&#xff08;Quicksort&#xff09;由英国计算机科学家Tony Hoare于1959年发明&#xff0c;是一种经典的排序算法&#xff0c;被广泛应用于计算机科学领域。快速排序&#xff08;Quick Sort&#xff09;是一种常见的基于比较的排序算法&#…

阿里云李飞飞:数据库将迎来“四化”趋势

伴随着数字经济的高速发展&#xff0c;越来越多的企业管理者都开始认识到数据才是企业最宝贵的资产&#xff0c;并为此不断加速企业的数字化转型与升级。而在数据库领域&#xff0c;云原生已经当仁不让地成为了当下最炙手可热的技术趋势之一。那么在云原生的时代大潮之下&#…

C++ STL之string容器

目录一、C与C字符串的差别二、string类对象的容量操作三、string类中的常见API总览1.构造2.赋值重载赋值操作符 成员函数 assign3.存取重载下标获取操作符 [ ]成员函数 at4.拼接重载复合操作符 成员函数 append5.查找成员函数 find成员函数 rfind成员函数 replace6.比较成员函数…

python接口自动化测试 之mock模块基本使用介绍

目录 mock作用 解决依赖问题&#xff0c;达到解耦作用 模拟复杂业务的接口 单元测试 前后端联调 mock类解读 mock实际使用 一个未开发完成的功能如何测试&#xff1f; 一个完成开发的功能如何测试&#xff1f; mock装饰器 mock作用 解决依赖问题&#xff0c;达到解耦…

AutoCAD2021安装教程图解+系统要求

AutoCAD2021具有完善的图形绘制功能&#xff0c;是一款非常实用的CAD图形制作软件&#xff0c;这款软件在业内也拥有极高的知名度&#xff0c;基本上绘图专业相关人员都会使用这款软件&#xff0c;来进行设计绘图。在软件中&#xff0c;为用户打造了超多实用的工具&#xff0c;…

python学习路线图(2023详细版)建议收藏

Python是一种面向对象的程序设计语言&#xff0c;由Python3演变而来&#xff0c;Python的目标是简单、可扩展并且高效。Python可以作为 Web应用程序、桌面应用程序和桌面 Web应用程序开发的理想语言&#xff0c;并且有很多优点它可以使用一些简单的参数和函数、Python支持多种数…

【Linux 网络编程5】网络/数据链路层--IP协议,MAC帧协议和ARP协议

IP协议格式和字段含义4位版本&#xff1a;IPv4或者Ipv6(他们两个不兼容)&#xff1b;4位首部长度&#xff1a;报头首部长度*4&#xff1b;8位服务类型&#xff1a;3位优先权字段(已经弃用), 4位TOS字段, 和1位保留字段(必须置为0)&#xff1b; 4位 TOS分别表示: 最小延时, 最大…

【SpringCloud】1、服务网关Gateway

这里写目录标题1.网关的介绍2.GateWay2.1 GateWay介绍1.网关的介绍 大家都知道在微服务架构中, 一个系统会被拆分为很多个微服务, 那么作为客户端要如何去调用这么多的微服务呢? 如果没有网关的存在, 我们只能在客户端记录每个微服务的地址, 然后分别去调用 这样的架构, 会…

2023-04-14 使用纯JS实现一个2048小游戏

文章目录一.实现思路1.2048的逻辑2.移动操作的过程中会有三种情况二.代码部分:分为初始化部分和移动部分1.初始化部分1.1.生成第一个方块:1.2.生成第二个方块:2.移动过程部分:三.实现代码1.HTML部分2.CSS部分3.JS部分3.1.game对象的属性3.2.game对象的start方法3.3.game对象的r…

材料科学基础学习指导-吕宇鹏-名词和术语解释-第5章:相图

目录 第一部分 第二部分​​​​​​​ 第三部分 第四部分​ 第一部分 1.1组元&#xff1a;是材料科学中的基本术语。意思是组成合金的独立的、最基本的单元。 1.2相&#xff1a; 指合金中具有同一聚集状态、同一晶体结构和性质并以界面相互隔开的均匀组成部分。​​​​…

【DS】河南省第十三届ICPC大学生程序设计竞赛 J-甜甜圈

明天就要省赛了&#xff0c;感觉已经寄了捏 J-甜甜圈_河南省第十三届ICPC大学生程序设计竞赛&#xff08;重现赛&#xff09; (nowcoder.com) 题意&#xff1a; 思路&#xff1a; 直接模拟复杂度太高&#xff0c;因此考虑用DS优化 我们考虑用树状数组维护 在用线段树和树状…