12.串,串的存储结构与模式匹配算法
目录
一. 一些术语
二. 串的类型定义
(1)串的顺序存储结构
(2)串的链式存储结构
三. 串的模式匹配算法
(1)BF算法
(2)KMP算法
四. 案例实现
串(String)---零个或多个任意字符组成的有限序列。

一. 一些术语
子串:串中任意个连续字符组成的子序列称为该串的子串
主串:包含子串的串相应地称为主串
字符位置:字符在序列中的序号为该字符在串中的位置
子串位置:子串第一个字符在主串中的位置
空格串:由一个或多个空格组成的串,与空串不同
例如:给定字符串a、b、c、d,a='BEI',b= 'JING',c='BEIJING',d='BEI JING'
它们的长度是: 3,4,7,8;
c的子串是:a,b;
d的子串是:a,b;
a在c中的位置是:1;a在d中的位置是:1;
b在c中的位置是:4;a在d中的位置是:5;
串相等:当且仅当两个串的长度相等并且各个对应位置上的字符都相同时,这两个串才是相等的。
二. 串的类型定义
串的抽象数据类型定义:同线性表,只不过处理对象是字符。
ADT String{数据对象:D={ ai | ai ∈ElemSet, i=1,2..,n, n≥0 }数据关系:R1= { <ai-1, ai >| ai-1, ai∈D, i=2,...,n }基本操作:StrAssign (&T,chars) //串赋值StrCompare (S,T) //串比较StrLength (S) //求串长Concat(&T,S1,S2) //串连结Index(S,T,pos) //求子串的位置...还有其他操作...
}ADT String
与前面完全相同,串也可分为顺序串和链串。
(1)串的顺序存储结构
#define MAXLEN 255
typedef struct{char ch[MAXLEN+1]; //存储串的一维数组int length; //串的当前长度
}SString;
说明:实际存储时通常是char ch[MAXLEN+1],然后把第一个位置空出,这在处理一些问题时会简便一些。
(2)串的链式存储结构
和链表不同的是,我们可以在一个结点有多个数据元素,这种结点我们称之为块,可以显著提高存储密度。

# define CHUNKSIZE 80 //块的大小可自定义
typedef struct Chunk{char ch[CHUNKSIZE];struct Chunk *next;
}Chunk; //定义一个块的结点typedef struct{Chunk *head,*tail; //串的头指针和尾指针int curlen; //串的当前长度
}LString; //字符串的块链结构
三. 串的模式匹配算法
模式匹配算法的目的:确定主串中所含子串(模式串)第一次出现的位置 (定位)。针对模式匹配问题,我们有BF算法(Brute-Force, 又称古典的、经典的、朴素的、穷举的)和KMP算法(速度快),下面介绍这两种算法。
(1)BF算法
BF算法采用的基本思想是穷举法。将主串的第pos个字符和模式串的第一个字符比较。若相等,继续逐个比较后续字符;若不等,从主串S的下一字符起,重新与模式串T的第一个字符比较。例如,目标串的长度m=6,模式串的长度n=4。则先将目标串的1-4位与模式串对应1-4位逐个比较(i=1,j=1),然后起始位置加1,将目标串的2-5位与模式串对应1-4位逐个比较(i=2,j=1),最后将目标串的3-6位与模式串对应位逐个比较(i=3,j=1)。如果这时候还没有找到,则返回0,表示目标串中不存在对应的模式串。
这里还需要牵扯到一个回溯的问题:模式串T比较到第j位时发现匹配不成功,这个时候要进入下一轮匹配。模式串T中j直接置1(前面讲了,字符串第一个索引为0的位置空出来),那么目标串S中i应该置多少呢?上一轮匹配中模式串T从1到j位,往后挪了j-1步,所以目标串S中第一个被比较的字符所有是i-(j-1),然后现在我们要进入下一轮循环,从这个字符的下一个字符开始,因此回溯的位置应该是i-(j-1)+1=i-j+2。
当匹配成功时,模式串T中指针j指向的位置索引应该是1+T.length,最后一个元素的下一个元素为空,退出循环,在此之前所有字符都匹配成功。所以返回的索引值应该是此刻的i值减去模式串的长度i-T.length。
下面给出BE算法的代码描述:
int Index_BF(SString S, SString T, int pos){int i=pos, j=1; //从主串第pos位开始查找while (i<=S.length && j<=T.length) {if (S.ch[i]==T.ch[j]) {++i; ++j;} //本字符对应位置匹配成功,主串和子串依次匹配下一个字符else {i=i-j+2;j=1;} //本字符匹配不成功,主串、子串指针回溯重新开始下一次匹配}if (j>=T.length) return i-T.length; //这个时候在主串中找到了子串,返回匹配的第一个字符的下标 else return 0; //直到所有循环结束仍没有在主串中找到子串,模式匹配不成功
}
最后讨论算法的时间复杂度,如果主串S,子串T的长度为m,n,最多需要进行的循环次数是(m-n+1)次,每次比较n次,则最坏情况下的时间复杂度是O((m-n+1)*n)。若n<<m,可简化为O(mn)。
(2)KMP算法
此部分难度较大,建议看王道的视频动画演示,这里总结一下怎么求next数组和nextval数组:
4.2_2_KMP算法_哔哩哔哩_bilibili
https://www.bilibili.com/video/BV1b7411N798?p=36&vd_source=7bf292964a807d18168b0c665fed431cnext数组的求法(手算练习):
- next[1]都无脑写0,next[2]都无脑写1;
- 其他next:在不匹配的位置前,划一根美丽的分界线,模式串一步一步往后退,直到分界线之前“能对上”,或模式串完全跨过分界线为止。此时j指向哪儿,next数组值就是多少。

例如,对于字符串google:
| g | o | o | g | l | e | |
| next[0] | next[1] | next[2] | next[3] | next[4] | next[5] | next[6] |
| 0 | 1 | 1 | 1 | 2 | 1 |
KMP算法实际上就是改变了指针的回溯位置,主串中指针不回溯,子串中指针回溯的位置由next数组确定。next数组的作用就是:当子串的第j个字符失配时,从子串的第next[i]的继续往后匹配,而不一定非要从1开始。

nextval数组求解:
在此基础上进一步优化next数组,具体操作是,首先解出next数组,然后用以下步骤优化:
nextval [1]=0;
for (int j=2; j<=T.length; j++) {if (T.ch[next [j]]==T.ch[j])nextval[j]=nextval[next[j]];elsenextval[j]=next[j];
}
例如,对以下字符串:
| a | b | a | b | b | a | |
| next[0] | next[1] | next[2] | next[3] | next[4] | next[5] | next[6] |
| next数组 | 0 | 1 | 1 | 2 | 3 | 4 |
| nextval数组 | 0 | 1 | 0 | 1 | 0 | 4 |
四. 案例实现
对于病毒检测:患病时,患者的DNA中包含病毒的DNA。但是病毒的DNA是环状的,也就是说假如aab是病毒的DNA,则aba,baa都是病毒的DNA。如图:

算法的主要思想如下:
- 对于每一个待检测的任务,假设病毒DNA序列的长度是m,因为病毒DNA序列是环状的,为了线性取到每个可行的长度为m的模式串,可将存储病毒DNA序列的字符串长度扩大为2m,将病毒DNA序列连续存储两次。
- 然后循环m次,依次取得每个长度为m的环状字符串,将此字符串作为模式串,将人的DNA序列作为主串,调用BF算法进行模式匹配。
- 只要匹配成功,即可中止循环,表明该人感染了对应的病毒;否则,循环m次结束循环时,可通过BF算法的返回值判断该人是否感染了对应的病毒。
相关文章:
12.串,串的存储结构与模式匹配算法
目录 一. 一些术语 二. 串的类型定义 (1)串的顺序存储结构 (2)串的链式存储结构 三. 串的模式匹配算法 (1)BF算法 (2)KMP算法 四. 案例实现 串(String)---零个或多个任意字符…...
Ribbon:listOfServers ,${variableName:defaultValue}
解释: 配置了address的地址,请求会走address,也就是http://127.0.0.1:8081,通常用户与别的后端服务进行联调设置为其本地服务的ip。 如果address的地址被注释掉,如下面所示,类似这样的占位符${variableName:defaultVa…...
TensorFlow二元-多类-多标签分类示例
探索不同类型的分类模型,使用 TensorFlow 构建二元、多类和多标签分类器。 二元分类 简述 逻辑回归 二元交叉熵 二元分类架构 案例:逻辑回归预测获胜团队 多类分类 简述 Softmax 函数 分类交叉熵 多类分类架构 案例:预测航天飞机…...
【回眸】牛客网刷刷刷!(七)——通信协议之 网络通讯
目录 前言 1、TCP/IP分层模型 2、ARP缓存 3、TCP 协议之所以提供可靠传输,不怕丢包、乱序的主要的原因是 4、以太网数据链路层MII/GMII/RMII/RGMII四种常用接口 5、在以太网通信协议LWIP中,数据包管理机构采用数据结构pbuf 分类包括 6、关于以太网…...
MySQL 安装配置
MySQL 安装配置 MySQL 是最流行的关系型数据库管理系统,由瑞典MySQL AB公司开发,目前属于Oracle公司。 MySQL所使用的SQL语言是用于访问数据库的最常用标准化语言。 MySQL由于其体积小、速度快、总体拥有成本低,尤其是开放源码这一特点,一般中小型网站的开发都选择MySQL…...
【0824作业】C++ 拷贝赋值函数、匿名对象、友元、常成员函数和常对象、运算符重载
一、思维导图 二、作业:实现关系运算符的重载 关系运算符重载 概念: 种类:>、>、< 、< 、 、!表达式:L#R (L表示左操作数,R表示有操作数,#表示运算符)左操作数:既可以是左值也可以…...
ubuntu 22.04 LTS openai triton 安装
第一种方法: pip install triton 第二种方法,安装最新的版本: pip install -U --index-url https://aiinfra.pkgs.visualstudio.com/PublicPackages/_packaging/Triton-Nightly/pypi/simple/ triton-nightly 第三种方法: git c…...
Android SDK 上手指南||第七章 Java应用程序编程
第七章 Java应用程序编程 如果大家已经对Java非常熟悉,那么不妨直接忽略这部分内容。如果大家的技巧还存在局限或者对Java这种语言只闻其名,那么本文将为各位解答很多在Android开发当中经常遇到的问题。需要注意的是,这篇文章并不能作为Java…...
Vue 框架如何获取数组中的值?
在Vue框架中,获取数组中的值可以通过以下几种方式实现: 1、使用数组索引: 可以使用数组的索引来获取特定位置的值。在Vue中,可以通过在模板中使用差值表达式或指令来获取数组中的值。例如: <div>{{ myArray[0]…...
如何成立一家音频芯片/算法设计公司
一 如何成立一家音频芯片设计公司? 要成立一家音频芯片设计公司,可以按照以下步骤进行: 市场调研:了解音频芯片市场的需求和竞争情况,确定目标客户和定位。 制定商业计划:根据市场调研的结果࿰…...
用docker-compose搭建LNMP
docker-compose搭建LNMP 一、compose 的部署1.Docker Compose 环境安装 二、编写Docker Compose1.准备依赖文件,配置nginx2.配置mysql3.配置php4.编写docker-compose.yml5.执行6.查看 一、compose 的部署 (1)公司在实际的生产环境中,需要使用…...
JavaScript:基本语法(变量与函数的定义与使用)
文章目录 script 标签srcdefer 延迟加载 基本语法定义变量 与 使用变量基本类型typeof 查看变量类型复合类型数组类型定义对象类型定义 函数定义函数使用函数 script 标签 src 和scc一样可以内嵌也可以外src外引。 一般是推荐外引。 <script src"idx.js">&l…...
树莓派4B上安装Gitlab
参考连接: 树莓派上使用 GitLab 搭建专业 Git 服务 | 树莓派实验室 gitlab reconfigure 卡住 ruby_block[wait for redis service socket] action run_芹菜学长的博客-CSDN博客 以及用到了讯飞星火 系统版本信息 1.进入 giblab安装页面gitlab/gitlab-ce - Instal…...
JVM 之字节码(.class)文件
本文中的内容参考B站尚硅谷宋红康JVM全套教程 你将获得: 1、掌握字节码文件的结构 2、掌握Java源代码如何在JVM中执行 3、掌握一些虚拟机指令 4、回答一些面试题 课程介绍 通过几个面试题初始字节码文件为什么学习class字节码文件什么是class字节码文件分析c…...
neo4j函数
1、断言函数 1all()判断是否一个断言适用于列表中的所有元素2all()判断是否一个断言至少适用于列表中的一个元素3none()如果断言不适用于列表中的任何元素,则返回true4single()如果断言刚好只适用于列表中的某一个元素,则返回true5exists()如果数据局库…...
wazuh初探系列一 : wazuh环境配置
目录 方法一:一体化部署 安装先决条件 第一步、安装所有必需的软件包 第二步、安装Elasticsearch 1、添加 Elastic Stack 存储库 安装 GPG 密钥: 添加存储库: 更新源: 2、Elasticsearch安装和配置 安装 Elasticsearch 包…...
【2023】Spring Validation中@NotNull注解、@NotBlank注解介绍以及使用
【2023】Spring Validation中NotNull注解、NotBlank注解介绍以及使用 前言一、简介spring-validation框架的常用注解 二、代码实现添加依赖1、实体举例2、Controller层:3、统一异常处理4、结果返回验证通过返回验证失败返回 前言 平常我们在编写代码的时候总需要很多if判空&am…...
nodejs+vue养老院管理系统 u1yrv
本智慧养老中心管理系统是为了提高用户查阅信息的效率和管理人员管理信息的工作效率,可以快速存储大量数据,还有信息检索功能,这大大的满足了老人信息和管理员这两者的需求。操作简单易懂,合理分析各个模块的功能,尽可…...
高效PDF校对:释放高质量内容的力量
在数字化世界中,内容是王者。随着企业和个人越来越依赖数字文档进行沟通、分享和创新,我们在PDF中传递的内容的质量变得至关重要。在这里,我们将探索高效的PDF校对如何帮助您释放高质量内容的真正潜力。 超越仅仅是“正确” 当我们谈论PDF校…...
【Git游戏】提交的技巧
修改历史的提交 rebase 通过git rebase -i 将要修改的提交提到最前端, 然后修改,再通过git commit --amend提交该记录,最后通过git rebase -i 在替换会原始的位置 (该过程中有可能会产生rebase confict) cherry-pick …...
安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...
【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...
NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...
Spring AI与Spring Modulith核心技术解析
Spring AI核心架构解析 Spring AI(https://spring.io/projects/spring-ai)作为Spring生态中的AI集成框架,其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似,但特别为多语…...
LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf
FTP 客服管理系统 实现kefu123登录,不允许匿名访问,kefu只能访问/data/kefu目录,不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...
Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)
引言 工欲善其事,必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后,我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集,就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...
Ubuntu系统多网卡多相机IP设置方法
目录 1、硬件情况 2、如何设置网卡和相机IP 2.1 万兆网卡连接交换机,交换机再连相机 2.1.1 网卡设置 2.1.2 相机设置 2.3 万兆网卡直连相机 1、硬件情况 2个网卡n个相机 电脑系统信息,系统版本:Ubuntu22.04.5 LTS;内核版本…...
ubuntu22.04 安装docker 和docker-compose
首先你要确保没有docker环境或者使用命令删掉docker sudo apt-get remove docker docker-engine docker.io containerd runc安装docker 更新软件环境 sudo apt update sudo apt upgrade下载docker依赖和GPG 密钥 # 依赖 apt-get install ca-certificates curl gnupg lsb-rel…...
