字符串 --- 找子串匹配算法

news2024/10/3 8:23:45

1.基本介绍

主串:形如 “hello world”的字符串作为一个整体

子串:上面主串的一部分如“world”

在计算机世界,主串找子串的模式很常见,比如要在word文件中找一句指定的话,那么面对海量的信息,我们匹配算法也有不断的优化,本文会介绍不同的匹配算法和给出对应的代码实现。

模式串:要在主串中找子串的那个字符串。

2.简单匹配--BF算法(暴力搜索)

1.实现

主串为n,子串为m。用一个下标,指向主串并且遍历,依次对应字串的字符,如果不同则指针往下走;如果相同则判断下一个字符是否相同,如果能匹配返回下标,不匹配返回0。(这里的字串开头下标为1,所以0下标没有用来存储数据)

1.如果不匹配,i要变成i-j+2,也就是i和j都遍历的原先位置的下一个;

2.匹配,则i++,j++;

3.如果j走到最后,则说明最后j大于T._len,那么返回的i原先的值;即为i-T._len;

4.不匹配,则直接return 0;

struct String
{
	char* _ch;
	size_t _len;
};//ch中的ch[0]位置不存放东西

//S为主串,T为子串
int Index(String S, String T)
{
	int i = 1, j = 1;
	while (i <= S._len && j <= T._len)
	{
		//判断不匹配,i需要回到原来的位置的后一个
		if (S._ch[i] != T._ch[j])
		{
			i = i - j + 2; //i-j+1得到的是原先的i位置,再+1
			j = 1; //
		}
		//匹配,下面再对比
		else
		{
			i++;
			j++;
		}
	}
	if (j > T._len)
		return i - T._len; // 返回i原先的位置
	return 0;  //走到这里说明没有,返回0
}

2.分析

前提条件:S有n个,T有m个

最坏的情况:每个字串都检查了m次,一共检查了n-m+1次,那么其复杂度为O(nm)

最好情况:只要检查一次,对比了m个数据,那么其复杂度为O(m)

2.KMP算法

1.引入

分析为什么BF算法如此之墨迹

1.BF之所以慢的核心点其实是i是依次遍历的,j也是依次遍历的

2.而之所以ij都依次遍历,其实该算法是将元素一视同仁了,在这套算法下,主串不管是什么都不会影响算法的走向

3.就是这种一视同仁的思想,以至于i跟j对比遍历过,一旦对比失败,i又回溯到前面遍历过的位置,已知晓的信息又变成了未知的东西

4.但是那些遍历过的信息何尝不是一种可以用来处理优化算法的东西呢?i不回溯,前面的信息保留,j也可以通过保留的信息知道哪些东西是不需要再遍历一次,直接往后到需要的位置处。

5.那么KMP的核心就是i不回溯,j通过之前i遍历的信息,省略一些遍历直接匹配有效要匹配的位置跟i的字符进行比较

6.那么现在的问题就变成了,怎么得知这些有效信息,以及如何保存呢? -- 其实是next数组来解决该问题的

2.next数组理论

其中心思想就是:当字串的第j位置不匹配时,要怎么移动子串和主串的i(不回溯)重新对比

用例子更好说明,直接看图

3.优化next数组

本质就算next数组中的指向下标对应的字符和next位置的字符是否相等

1.相等,说明了其实两个等价,既然next位置都对不上,那指向的那个字符跟next位置字符一样,说白了不还是一样对不上吗,所以可以直接替换成next所指位置的next值

2.不相同,则无法优化

if(ch[ next[ j ] ] == ch[ j ]) ------- next[ j ] =next[ next[ j ] ]

4.next数组实现

为了得到next数组,我们需要一些基础的定义:

前缀:以aacfd为例子,{a,aa,aac,aacf}都是前缀,不包含为尾字母

后缀:以aacfd为例子,{d,fd,cfd,acfd}都是后缀,不包含为头字母

最长相等前后缀:以aacfd为例子,都对不上,所以最长相等前后缀为0

前缀表:指前缀的最长相等前后缀对应的表

{a --> 0,aa  --> 1,aac --> 0,aacf --> 0}

此时,前缀表就是一种next表

1.某个位置的字符不匹配,前一个字符需要得到最长相等前后缀

2.最长相等前后缀意味着,在该字符的前缀长度为2跟自己相互匹配,那反映到主串也是一样(换句话说,主串的前缀和子串的后缀相等的最长数都不需要比较了,因为相同,我们只要比较子串的后一个位置即可),那么我们要跳到与之匹配的下一个进行判断

前缀表所有元素往后移,第一位为-1,最后全体+1,这样得到的就是最上面原始的next数组

// next数组,s为子串
void GetNext(int* next, string s)
{
	int i, j;
	//1.初始化
	j = 0; //j为前缀末尾,j最后也是放入next数组的值
	next[0] = 0;

	for (i = 1; i < s.size(); i++)
	{
		while (j >= 0 && s[i] != s[j])
			j = next[j - 1];
		if (s[i] == s[j])
			j++;
		next[i] = j;
	}
}

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

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

相关文章

最新入河排污口设置论证、水质影响预测与模拟、污水处理工艺分析及典型建设项目入河排污口方案报告书实例分析

目录 专题一 入河排污口设置论证相关法律与制度解读 专题二 水域纳污能力核算方法 &#xff08;讲授与实操相结合&#xff09; 专题三 入河排污口设置方案、分析范围、论证范围、模型预测范围确定方法 专题四 入河排污口所在水域水质现状与取水、排污状况分析 专题五 入河…

React State 状态

React State(状态) React 把组件看成是一个状态机&#xff08;State Machines&#xff09;。通过与用户的交互&#xff0c;实现不同状态&#xff0c;然后渲染 UI&#xff0c;让用户界面和数据保持一致。 React 里&#xff0c;只需更新组件的 state&#xff0c;然后根据新的 s…

SPI通讯

1、介绍 SPI是高速、全双工、同步的通信总线。 SPI应用于存储芯片、AD转换器及LCD中。 同步、异步区别&#xff1a;是否有时钟线&#xff0c;例如SPI、I2C是同步通信&#xff0c;需要用到时钟线&#xff0c;串口是异步通信&#xff0c;没有时钟线。 SPI通信需要四根线&…

【数据结构】单链表(详解)

【数据结构】单链表&#xff08;详解&#xff09; 1.前言1.1本章节重点1.2 什么是单链表1.3 结构体设计1.4结构体传参 2. SList.h展示3. SList.c展示4. 各个接口函数的实现4.1 尾插4.2 打印4.3 头插4.3.1内存开辟函数4.3.2插入 4.4 尾删4.5 头删4.6 查找4.7 给定一个位置在这个…

今天面了个字节跳动拿35K出来的,真是砂纸擦屁股,给我露了一手啊

今年的金三银四已经快要结束了&#xff0c;很多小伙伴收获不错&#xff0c;拿到了心仪的 offer。 各大论坛和社区里也看见不少小伙伴慷慨地分享了常见的面试题和八股文&#xff0c;为此咱这里也统一做一次大整理和大归类&#xff0c;这也算是划重点了。 俗话说得好&#xff0c…

为什么选择学习python?

对于编程初学者来说&#xff0c;python更加简单易学&#xff0c;便于初学者入门~ 学Python之前&#xff1a;这玩意真有传说中那么好么&#xff1f; 学Python之后&#xff1a;唉呀妈呀&#xff0c;真香~ 别人花2天时间处理的Excel数据&#xff0c;你用Python 只花1小时&#…

若依移动端Ruoyi-App——字典使用

1. 引入dict 将若依前后端分离中的dict文件夹拷贝到api的system里 2.在页面中引入方法 import { getDicts } from "/api/system/dict/data"; 3. 前端 <span>{{statusType}}</span> 4. 加载数据字典 export default {data() {return {statusOptions…

LeetCode:剑指 Offer 58 - II. 左旋转字符串

&#x1f34e;道阻且长&#xff0c;行则将至。&#x1f353; &#x1f33b;算法&#xff0c;不如说它是一种思考方式&#x1f340; 算法专栏&#xff1a; &#x1f449;&#x1f3fb;123 一、&#x1f331;剑指 Offer 58 - II. 左旋转字符串 题目描述&#xff1a;字符串的左旋…

正则表达式 - 电话号码

正则表达式是描述一组字符串特征的模式&#xff0c;用来匹配特定的字符串。 一、需求 写一个正则表达式匹配电话号码&#xff0c;并且括号、连字符或点号都是可选的。假定合规数据只包含以下15种匹配模式之一&#xff1a; xxxxxxx 8277019xxx.xxxx 82…

【Microsoft Edge】详解 Edge 的扩展程序

Edge 扩展程序 安装与卸载显示与隐藏开启与关闭导入与导出导出导入操作好处与优势 安装与卸载 可从 https://microsoftedge.microsoft.com/addons?hlzh-CN 获取你想要的扩展程序。 也可以使用 Chrome Web Store &#xff0c;但出于某些原因&#xff0c;需要科学上网。 获取后…

初赛-排列组合概念

1.加法原理: 完成一个工程可以有n类办法&#xff0c;a[i](1<i<n) 代表第i类方法的数目。 那么完成这件事共有 S a[1]a[2]...a[n]种不同的方法。 2.乘法原理: 完成一个工程需要分n个步骤&#xff0c;a[i](1<i<n) 代表第i个步骤的不同方法数目。 那么完成这件…

DnsAddressResolverGroupFactory.create(DnsAddressResolverGroupFactory.java:33)

今天处理了一个dubb升级造成的包冲突&#xff0c;记录下&#xff0c;希望能帮到一些有同样问题的小伙伴&#xff0c;并且将自己解决包冲突的想法总结下 背景&#xff1a; 因为dubbo出现安全漏洞&#xff0c;公司的安全组要求将dubbo的版本由2.7.3-SNAPSHOT 升级到 2.7.3.7-RE…

Windows 10, version 22H2 (2023年3月) 简体中文版、英文版下载

Windows 10, version 22H2 (updated March 2023) 简体中文版、英文版下载 Windows 10 22H2 2023 年 3 月更新 Windows 10 是微软公司推出的一款操作系统&#xff0c;是 Windows 系列操作系统的最新版本&#xff0c;于2015年7月正式发布。Windows 10 被设计为既适用于桌面电脑和…

ActiveMQ使用(二):在JavaScript中使用mqtt.js

ActiveMQ使用(二):在JavaScript中使用mqtt.js 1. 环境准备 jQuery-1.10 下载地址:https://www.jsdelivr.com/package/npm/jquery-1.10.2?tabfilesmqtt.js 4.3.7: 下载地址:https://www.jsdelivr.com/package/npm/mqtt 2. 相关代码 <!DOCTYPE html> <html lang&q…

引用【C++初阶】

目录 一、引用 1、概念 2、特性 3、常引用 4、使用常景 5、传值与传引用的效率性能比较 6、指针和引用的区别 一、引用 1、概念 引用不是新定义一个变量&#xff0c;而是给已存在的变量取一个别名&#xff0c;编译器不会为引用变量开辟内存空间&#xff0c;它和它引用的…

线程方法,生命周期,线程状态,Synchronized,

package com.hspedu.method;/*** author 韩顺平* version 1.0*/ public class ThreadMethod01 {public static void main(String[] args) throws InterruptedException {//测试相关的方法T t new T();t.setName("老韩");t.setPriority(Thread.MIN_PRIORITY);//设置优…

初识网络安全应急响应

初识网络安全应急响应 1.应急响应的基本能力2.应急响应的基本流程 1.应急响应的基本能力 一、数据采集、存储和检索 能对全流量数据协议进行还原&#xff1b;能对还原的数据进行存储&#xff1b;能对存储的数据快速检索。 二、事件发现 能发现高级可持续威胁&#xff08;AP…

【Redis】Redis十大数据类型—集合set

介绍 set类型是一个无序并唯一的键值集合&#xff0c;set的存储顺序不会按照插入的先后顺序进行存储。 一个集合最多可以存储2^32-1个元素。 set类型除了支持集合内的增删改查&#xff0c;同时还支持多个集合取交集、并集、差集。 Set 类型和 List 类型的区别如下&#xff1…

cgroups 实践

CPU 限制 1. 创建测试的 cgroup 在 /sys/fs/cgroup/cpu 下面创建自己的 cgroups 测试目录&#xff0c;该目录会自动创建一些文件&#xff0c;对进程或者线程的控制都可以通过修改这些文件内容自动完成。 tasks&#xff1a;被 cgroup 管理的进程 cpu.cfs_period_us&#xff1a…

多线程(九):JUC组件

在来时juc组件前&#xff0c;我们先把上一章遗漏的部分给补上。 synchronized 实现策略&#xff1a;锁升级&#xff1a; 无锁 -> 偏向锁 -> 轻量级锁 -> 重量级锁 还有一个 &#xff1a; 锁消除 锁消除即删除不必要的加锁操作。JVM在运行时&#xff0c;对一些“…