2023王道考研数据结构笔记第四章串
第四章 串
4.1 串的定义
4.1.1 串的相关概念
-
串:即字符串(String)是由零个或多个字符组成的有限序列。一般记为S=‘a1a2…an’ (n>=0)
其中S是串名,单引号(注:有的地方用双引号,如Java、C,有的地方用单引号,如Python)括起来的字符序列是串的值;ai可以是字母、数字或其他字符。
-
串的长度:串中字符的个数 n,n = 0 时的串称为空串(用∅\emptyset∅表示)。
-
子串:串中任意个连续的字符组成的子序列。
-
主串:包含子串的串。
-
字符在主串中的位置:字符在串中的序号。(注意:位序从1开始而不是从0开始)
-
子串在主串中的位置:子串的第一个字符在主串中的位置 。
-
空串 vs 空格串 M=‘’ M是空串 N=’ ’ N是由三个空格字符组成的字符串,每个空格字符占1B
-
串 vs 线性表
① 串是一种特殊的线性表,数据元素之间呈线性关系
② 串的数据对象限定为字符集(如中文字符、英文字符、数字字符、标点字符等)
③ 串的基本操作,如增删改查等通常以字串为操作对象
4.1.2 串的基本操作
StrAssign(&T, chars)
:赋值操作。把串 T 赋值为 chars。StrCopy(&T, S)
:复制操作。由串 S 复制得到串 T。StrEmpty(S)
:判空操作。若 S 为空串,则返回 TRUE,否则返回 FALSE。StrLength(S)
:求串长。返回串 S 中元素的个数。ClearString(&S)
:清空操作。将 S 清为空串。DestroyString(&S)
:销毁串。将串 S 销毁(回收存储空间)。Concat(&T, S1, S2)
:串联接。用 T 返回由 S1 和 S2 联接而成的新串 。SubString(&Sub, S, pos, len)
:求子串。用 Sub 返回串 S 的第 pos 个字符起长度为 len 的子串。Index(S, T)
:定位操作。若主串 S 中存在与串 T 值相同的子串,则返回它在主串 S 中第一次出现的位置;否则函数值为 0。StrCompare(S, T)
:比较操作。若 S>T,则返回值>0;若 S=T,则返回值=0;若 S<T,则返回值<0。
4.1.3 串的存储结构
1、静态数组实现(定长顺序存储)
#define MAXLEN 255 //预定义最大串长为255
typedef struct {char ch[MAXLEN]; // 每个分量存储一个字符int length; // 串的实际长度
} SString;
2、动态数组实现(堆分配存储)
typedef struct {char *ch; // 按串长分配存储区,ch指向串的基地址int length; // 串的长度
} HString;
HString S;
S.ch=(char *)malloc(MAXLEN*sizeof(char)); //用完需要手动free
S.length=0;
3、块链存储表示
默认情况下存储密度低,每个节点都只能存储一个字符
解决方法:一个结点存储多个字符
typedef struct StringNode{char ch; //存储密度低,每个字符1B,每个指针4Bstruct StringNode * next;
}StringNode,* String;typedef struct StringNode{char ch[4];struct StringNode *next;
}StringNode,* String; //存储密度提高
4.2 串的模式匹配
串的模式匹配:在主串中找到与模式串相同的子串,并返回其所在位置。
4.2.1 简单的模式匹配算法
思想:将主串中与模式串长度相同的字串拿出来,挨个与模式串对比
当子串与模式串某个对应字符不匹配时,就立即放弃当前子串,转而检索下一个子串
一个示例:
分析:
简单模式匹配算法的最坏时间复杂度是O(nm),即每个子串都要对比到最后一个字符,如下面这种情况:
- 主串:1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2
- 子串:1 1 1 1 1 1 1 1 2
其中,n和m分别是主串和模式串的长度。
最好的情况(对于每个子串都只需对比一次):
- 匹配成功:O(m)
- 匹配失败:O(n-m+1)=O(n-m)≈O(n)
4.2.2 KMP算法
朴素模式匹配算法的缺点:当某些子串与模式串能部分匹配时,主串的扫描指针i经常回溯,导致时间开销增加。
要了解子串的结构,首先需要了解以下几个概念:前缀、后缀和部分匹配值。
前缀:除了最后一个字符外,字符串的所有头部子串
后缀:除了第一个字符外,字符串的所有尾部子串
‘ab’的前缀是{a},后缀是{b},{a}∩{b}=∅,最长相等前后缀长度为0
'aba’的前缀为{a, ab},后缀为{a, ba}, {a, ab }∩{a, ba}={a),最长相等前后缀长度为1。
'abab '的前缀{a, ab,aba}∩后缀{b, ab, bab }={ab},最长相等前后缀长度为2。
'ababa '的前缀{a, ab,aba, abab }∩后缀{a , ba, aba, baba }={a, aba},公共元素有两个,最长相等前后缀长度为3。
故字符串’ababa’的部分匹配值为00123
接下来详解一下上面这个例子:
由上述方法求子串’abcac’的部分匹配值:
'ab’的前缀{a},后缀{b} {a}∩{b} = ∅
'abc’的前缀{a,ab}, 后缀{c, bc} {a,ab}∩{c, bc} = ∅
'abca’的前缀{a,ab,abc},后缀{a,ca,bca} {a,ab,abc}∩{a,ca,bca} = {a}
'abcac’的前缀{a,ab,abc,abca},后缀{c,ac,cac,bcac} {a,ab,abc}∩{c,ac,cac,bcac} = ∅
将其部分匹配值写成数组形式,就得到了部分匹配值(PM)的表:
编号 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|
S | a | b | c | a | c |
PM | 0 | 0 | 0 | 1 | 0 |
接下来可以使用PM表来进行字符串匹配,其过程如下
KMP算法的原理
当c与b不匹配时,已匹配’abca’的前缀a和后缀a为最长公共元素。已知前缀a与b、c均不同,与后缀a相同,故无须比较,直接将子串移动“已匹配的字符数–对应的部分匹配值”,用子串前缀后面的元素与主串匹配失败的元素开始比较即可。
对算法的改进
已知:右移位数=已匹配的字符数-对应的部分匹配值。写成:
Move=(j−1)−PM[j−1]Move=(j-1)-PM[j-1] Move=(j−1)−PM[j−1]
现在这种情况下,我们在匹配失败时,需要去查找它前一个元素的部分匹配值,这样使用起来有点不方便,故我们可以将PM表右移一位,这样哪个元素匹配失败,则直接看它自己的部分匹配值即可。
将上例的PM表右移一位,则得到了next数组
编号 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|
S | a | b | c | a | c |
next | -1 | 0 | 0 | 0 | 1 |
我们注意到:
1)第一个元素右移以后空缺的用-1来填充,因为若是第一个元素匹配失败,则需要将子串向右移动一位,而不需要计算子串移动的位数。
2)最后一个元素在右移的过程中溢出,因为原来的子串中,最后一个元素的部分匹配值是其下一个元素使用的,但显然已没有下一个元素,故可以舍去。
这样,上式就改写为:
Move=(j−1)−next[j]Move=(j-1)-next[j] Move=(j−1)−next[j]
就相当于将子串的比较指针回退到:
j=j−Move=j−((j−1)−next[j])=next[j]+1j=j-Move=j-((j-1)-next[j])=next[j]+1 j=j−Move=j−((j−1)−next[j])=next[j]+1
但为了让公式更加简洁,我们将next数组整体加1
next数组也可以写成:
编号 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|
S | a | b | c | a | c |
next | 0 | 1 | 1 | 1 | 2 |
最终子串指针变化公式为:
j=next[j]j=next[j] j=next[j]
在实际匹配过程中,子串在内存里是不会移动的,而是指针在变化,书中画图举例只是为了让问题描述得更加形象。next[j]的含义是:在子串的第j个字符与主串发生失配时,则跳到子串的next[j]位置重新与主串当前位置进行比较。
【重要】求next数组,根据如下示例来学习:
KMP算法的进一步优化
问题的产生:
所以引入了nextval数组,对KMP算法进行进一步优化。
故我们在模式串中,当前模式串p和对应的next数组p_next的模式串值相等时,继续查找对应p_next模式串的next数组对应的模式串,直到模式串对应的值不相等。
以下是匹配过程:
相关文章:

2023王道考研数据结构笔记第四章串
第四章 串 4.1 串的定义 4.1.1 串的相关概念 串:即字符串(String)是由零个或多个字符组成的有限序列。一般记为S‘a1a2…an’ (n>0) 其中S是串名,单引号(注:有的地方用双引号,如Java、C&am…...

【AI绘图学习笔记】深度学习相关数学原理总结(持续更新)
如题,这是一篇深度学习相关数学原理总结文,由于深度学习中涉及到较多的概率论知识(包括随机过程,信息论,概率与统计啥啥啥的),而笔者概率知识储备属实不行,因此特意开一章来总结(大部…...

CSGO服务器配置全贴纸插件方法教程
CSGO服务器配置全贴纸插件方法教程 关于插件的警告 一定要了解V社对于CSGO社区服务器的规定,全皮肤插件/全手套插件等,在设置了GSLT的情况下,是有可能被封禁GSLT账号的(所以慎用) 配置好服务器之后呢,想安…...

Python爬虫——使用socket模块进行图片下载
Python爬虫——使用socket模块进行图片下载什么是socket爬虫的工作流程socket爬取图片为什么能用socket能下载图片socket下载图片和request下载图片的区别使用socket下载一张图片使用socket下载多张图片方法1方法2什么是socket Socket 是一种通信机制,用于实现网络…...

通用游戏地图解决方案设计解析
前言: 在软件开发过程中,我们都希望能设计出一个稳健的,可维护的系统,为了实现这个目的,人们总结出了很多相关的设计原则,比如SOLID原则, KISS原则等等。SOLID每个字母代表了一种设计原则&…...

java @Autowired @Resource @Inject 三个注解的区别
javax.annotation.Resourcejdk 内置的,JSR-250 中的注解。依赖注入通过 org.springframework.context.annotation.CommonAnnotationBeanPostProcessor 来处理。org.springframework.beans.factory.annotation.Autowired org.springframework.beans.factory.annotati…...

「媒体分流直播」媒体直播和传统直播的区别,以及媒体直播的特点
传媒如春雨,润物细无声,大家好直播毋庸置疑已经融入到了我们生活的方方面面,小到才艺,游戏,大到政策的发布,许多企业和机构也越来越重视直播,那么一场活动怎么最大化的进行传播,一是…...

数据是如何在计算机中存储的
我们普通人对于数据存储的认识恐怕大多数都是从自己使用的电脑来的。现在几乎人手一台电脑,而我们的电脑存储着各种各样的文件,比如视频文件、音频文件和Word文档等。这些文件从计算机术语的角度都可以称为数据。 如图1-1所示是Windows 10 “我的电脑”的截图。通过该截图我…...

Day907.分区表 -MySQL实战
分区表 Hi,我是阿昌,今天学习记录的是关于分区表的内容。 经常被问到这样一个问题: 分区表有什么问题,为什么公司规范不让使用分区表呢? 一、分区表是什么? 为了说明分区表的组织形式,先创建…...

C++概览:工具链、基础知识、进阶及总结
本篇写给C初学者,作为概览,文中仅包含各方面基础知识,无深入分析。 C基础概念简介 C编译过程示意图 关键词:源文件、预编译、编译、汇编、链接 C工具链总结 cmake项目工程文件是一种中介工程文件,可以转化成其他…...

目标检测中回归损失函数(L1Loss,L2Loss,Smooth L1Loss,IOU,GIOU,DIOU,CIOU,EIOU,αIOU ,SIOU)
文章目录L-norm Loss 系列L1 LossL2 LossSmooth L1 LossIOU系列IOU (2016)GIOU (2019)DIOU (2020)CIOU (2020)EIOU (2022)αIOU (2021)SIOU (2022…...

JOSN数据转换和解析
文章目录JOSN数据转换和解析内容回顾Map 集合转成 JSON 字符串List 集合转换成 JSON 字符串Ajax 异步和同步异步概念同步概念异步和同步区别异步请求案例同步请求时间格式化旧时间 api 格式化格式化和解析的工具类JSTL 时间格式化JSTL 使用JOSN数据转换和解析 内容回顾 ajax …...

浅析Linux内核中进程完全公平CFS调度
一、前序 目前Linux支持三种进程调度策略,分别是SCHED_FIFO 、 SCHED_RR和SCHED_NORMAL;而Linux支持两种类型的进程,实时进程和普通进程。实时进程可以采用SCHED_FIFO 和SCHED_RR调度策略;普通进程则采用SCHED_NORMAL调度策略。从…...

安装 RustDesk 服务器 (适用 Rocky Linux, CentOS, RHEL 系列发行版)
环境:Rocky Linux 9.1 1. 安装 Docker Engine 可以参考 [[linux-docker-rocky-install]] https://cc01cc.com/2023/03/02/linux-docker-rocky-install/英文可以参考官方文档 Install Docker Engine on RHEL https://docs.docker.com/engine/install/rhel/ 2. 安装…...

23种设计模式-策略模式
策略模式是一种设计模式,它允许在运行时选择算法的行为。它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户端。在本文中,我们将深入探讨策略模式的概念和实际应用&#…...

C#开发的OpenRA的游戏主界面怎么样创建
通过前面加载界面布局数据,可以把整个界面逻辑的数据加载到内存, 但是这些数据怎么显示出来,又是没有定义的。比如前面定义了多个界面的布局, 又是怎么样知道需要显示哪一个界面? 现在就来解决这个问题,其实整个游戏都是可以通过yaml文件进行配置的, 所以我们需要从yaml…...

考研还是工作?两战失败老道有话说
老道入职第一周自我介绍谈谈考研谈谈工作新的启程自我介绍 大家好!在下是一枚考研失败两次的自认为聪明能干的有点小帅的实则超级垃圾的三非名校毕业的自动化渣男。大一下就加入实验室,在实验室焊板子、画板子、培训、打比赛外加摸鱼;参加过…...

引用是否有地址的讨论的
说在前头,纯属个人理解,关于引用是否有地址,实际上并没有一个很统一的说法, C标准没有规定一个引用是否需要占用一块内存。 这里引用知乎“C 中引用是一块内存的标记,那引用本身有地址吗_百度知道 (baidu.com)”里面的…...

1、JAVA 开发环境搭建 - JDK 的安装配置
文章目录一、下载 JDK81、官网地址:[**https://www.oracle.com**](https://www.oracle.com)二、安装 JDK1、鼠标右键安装包,以管理员身份运行(无脑下一步即可)2、细节说明三、配置环境变量1、为啥要配置环境变量呢?2、原因分析3、配置环境变量…...

【Storm】【六】Storm 集成 Redis 详解
Storm 集成 Redis 详解 一、简介二、集成案例三、storm-redis 实现原理四、自定义RedisBolt实现词频统计一、简介 Storm-Redis 提供了 Storm 与 Redis 的集成支持,你只需要引入对应的依赖即可使用: <dependency><groupId>org.apache.storm…...

算法代码题——模板
文章目录1. 双指针: 只有一个输入, 从两端开始遍历2. 双指针: 有两个输入, 两个都需要遍历完3. 滑动窗口4. 构建前缀和5. 高效的字符串构建6. 链表: 快慢指针7. 反转链表8. 找到符合确切条件的子数组数9. 单调递增栈10. 二叉树: DFS (递归)]11. 二叉树: DFS (迭代)12. 二叉树: …...

CentOS 7.9汇编语言版Hello World
先下载、编译nasm汇编器。NASM汇编器官网如下图所示: 可以点图中的List进入历史版本下载网址: 我这里下载的是nasm-2.15.05.tar.bz2 在CentOS 7中,使用 wget http://www.nasm.us/pub/nasm/releasebuilds/2.15.05/nasm-2.15.05.tar.bz2下载…...

CoreData数据库探索
CoreData是什么 Core Data 是苹果公司提供的一个对象-关系映射框架(Object-Relational Mapping,ORM),用于管理应用程序的数据模型。Core Data 提供了一个抽象层,使开发人员能够使用面向对象的方式访问和操作数据&…...

FreeRTOS入门
目录 一、简介 二、堆的概念 三、栈的概念 四、从官方源码中精简出第一个FreeRTOS程序 五、修改官方源码增加串口打印 一、简介 FreeRTOS是一个迷你的实时操作系统内核。作为一个轻量级的操作系统,功能包括:任务管理、时间管理、信号量、消息队列、…...

JVM运行时数据区划分
Java内存空间 内存是非常重要的系统资源,是硬盘和cpu的中间仓库及桥梁,承载着操作系统和应用程序的实时运行。JVM内存布局规定了JAVA在运行过程中内存申请、分配、管理的策略,保证了JVM的高效稳定运行。不同的jvm对于内存的划分方式和管理机…...

重装系统一半电脑蓝屏如何解决
小编相信大家在使用电脑或者给电脑重装系统的时候都遇到过电脑蓝屏等等故障问题。最近有用户就遇到了这样一个问题,问小编重装系统一半电脑蓝屏怎么办,那么今天小编就告诉大家重装系统一半电脑蓝屏的解决方法。 工具/原料: 系统版本&#x…...

SpringBoot(tedu)——day01——环境搭建
SpringBoot(tedu)——day01——环境搭建 目录SpringBoot(tedu)——day01——环境搭建零、今日目标一、IDEA2021项目环境搭建1.1 通过 ctrl鼠标滚轮 实现字体大小缩放1.2 自动提示设置 去除大小写匹配1.3 设置参数方法自动提示1.4 设定字符集 要求都使用UTF-8编码1.5 设置自动编…...

springboot整合redis
1.redis的数据类型,一共有5种.后面结合Jedis和redistemplate,以及单元测试junit一起验证 1)字符串 2)hash 3)列表 4)set(无序集合) 5)zset(有序集合) 2.Jedis的使用 a)引入依赖 <!--加入springboot的starter的起步依赖--><dependency><groupId>…...

【Java】Spring Boot下的MVC
文章目录Spring MVC程序开发1. 什么是Spring MVC?1.1 MVC定义1.2 MVC 和 Spring MVC 的关系2. 为什么学习Spring MVC?3. 怎么学习Spring MVC?3.1 Spring MVC的创建和连接3.1.1 创建Spring MVC项目3.1.2 RequestMapping 注解介绍3.1.3 Request…...

【项目精选】 塞北村镇旅游网站设计(视频+论文+源码)
点击下载源码 摘要 城市旅游产业的日新月异影响着村镇旅游产业的发展变化。网络、电子科技的迅猛前进同样牵动着旅游产业的快速成长。随着人们消费理念的不断发展变化,越来越多的人开始注意精神文明的追求,而不仅仅只是在意物质消费的提高。塞北村镇旅游…...