12.串,串的存储结构与模式匹配算法

news2024/11/22 15:12:57

目录

一. 一些术语

二. 串的类型定义

(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算法_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1b7411N798?p=36&vd_source=7bf292964a807d18168b0c665fed431cnext数组的求法(手算练习):

  • next[1]都无脑写0,next[2]都无脑写1;
  • 其他next:在不匹配的位置前,划一根美丽的分界线,模式串一步一步往后退,直到分界线之前“能对上”,或模式串完全跨过分界线为止。此时j指向哪儿,next数组值就是多少。

例如,对于字符串google:

google
next[0]next[1]next[2]next[3]next[4]next[5]next[6]
011121

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]];
    else
        nextval[j]=next[j];
}

例如,对以下字符串:

ababba
next[0]next[1]next[2]next[3]next[4]next[5]next[6]
next数组011234
nextval数组010104

四. 案例实现

对于病毒检测:患病时,患者的DNA中包含病毒的DNA。但是病毒的DNA是环状的,也就是说假如aab是病毒的DNA,则aba,baa都是病毒的DNA。如图:

算法的主要思想如下:

  • 对于每一个待检测的任务,假设病毒DNA序列的长度是m,因为病毒DNA序列是环状的,为了线性取到每个可行的长度为m的模式串,可将存储病毒DNA序列的字符串长度扩大为2m,将病毒DNA序列连续存储两次。
  • 然后循环m次,依次取得每个长度为m的环状字符串,将此字符串作为模式串,将人的DNA序列作为主串,调用BF算法进行模式匹配。
  • 只要匹配成功,即可中止循环,表明该人感染了对应的病毒;否则,循环m次结束循环时,可通过BF算法的返回值判断该人是否感染了对应的病毒。
     

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

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

相关文章

带你了解SpringBoot---开启Durid 监控(SQL 监控、SQL 防火墙、Web 应用、Session 监控等)

数据库操作–开启Durid 监控 整合Druid 到Spring-Boot 官方文档 使用手册: https://github.com/alibaba/druid 中文手册&#xff1a; https://github.com/alibaba/druid/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98English手册&#xff1a; https://github.com/alibaba/drui…

第十二届钧瓷文化旅游节主题曲:让世界看见钧瓷的魅力

下面是以产业&#xff0c;古镇&#xff0c;营销为主题专门为第十二届钧瓷文化旅游节创作的《让世界看见钧瓷的魅力》的歌词。 古镇千年的沉淀&#xff0c;窑火燃烧的传说 传承着古老的技艺&#xff0c;匠人们用心铸就 钧瓷的魅力&#xff0c;吸引着世界的目光 这里的风景&am…

Gitlab 安装全流程

Version&#xff1a;gitlab-ce:16.2.4-ce.0 简介 Gitlab 是一个开源的 Git 代码仓库系统&#xff0c;可以实现自托管的 Github 项目&#xff0c;即用于构建私有的代码托管平台和项目管理系统。系统基于 Ruby on Rails 开发&#xff0c;速度快、安全稳定。它拥有与 Github 类似…

双碳目标下DNDC模型建模方法及在土壤碳储量、温室气体排放、农田减排、土地变化、气候变化的应用

由于全球变暖、大气中温室气体浓度逐年增加等问题的出现&#xff0c;“双碳”行动特别是碳中和已经在世界范围形成广泛影响。国家领导人在多次重要会议上讲到&#xff0c;要把“双碳”纳入经济社会发展和生态文明建设整体布局。同时&#xff0c;提到要把减污降碳协同增效作为促…

态路小课堂丨光纤合束器介绍

TARLUZ态路 随着激光应用技术的发展&#xff0c;在材料加工、空间光通讯、遥感、激光雷达和光电对抗等诸多领域都需要更高功率、质量以及亮度的激光束。在单根光纤不能达到要求时&#xff0c;就可以通过光纤合束器对单纤激光器进行组束以获得更高功率。态路通信本文简单为您介绍…

聊聊智能眼镜的发展

目录 1.智能眼镜的概念 2.智能眼镜的原理 3.智能眼镜的功能 4.智能眼镜发展趋势 1.智能眼镜的概念 智能眼镜&#xff08;Smart Glasses&#xff09;是一种集成了计算和显示功能的眼镜设备&#xff0c;拥有增强现实&#xff08;AR&#xff09;或虚拟现实&#xff08;VR&…

python判断ip所属地区 python 判断ip 网段

前言 IP地址是互联网中唯一标识一个设备的地址&#xff0c;有时候需要判断一个IP地址所属的地区&#xff0c;这就需要用到IP地址归属查询。本文将介绍Python如何通过IP地址查询所属地区并展示代码。 一、 IP地址归属查询 IP地址归属查询又称IP地址归属地查询、IP地址归属地定…

vue3 报错: ‘defineProps‘ is not defined no-undef

错误 解决方案 修改.eslintrc.js文件&#xff0c;在基根节点添加如下内容&#xff1a; module.exports {globals: {defineProps: readonly,defineEmits: readonly,}, }

热烈祝贺汇隆成功入选航天系统采购供应商库

经过航天系统采购平台的严审&#xff0c;浙江汇隆晶片技术有限公司成功入选中国航天系统采购供应商库。航天系统采购平台是航天系统内企业采购专用平台&#xff0c;服务航天全球范围千亿采购需求&#xff0c;目前&#xff0c;已有华为、三一重工、格力电器、科大讯飞等企业、机…

20230822 Windows上使用find_package引入OpenCV报错

报错信息 打开Cmake项目时&#xff0c;find_package 报错&#xff1a; Found OpenCV Windows Pack but it has no binaries compatible with yourconfiguration.You should manually point CMake variable OpenCV_DIR to your build of OpenCVlibrary.原因 大概率原项目是在 …

基于springboot的社区生活缴费系统/基于javaweb的水电缴费系统

摘 要 网络的广泛应用给生活带来了十分的便利。所以把社区生活缴费管理与现在网络相结合&#xff0c;利用java语言建设社区生活缴费系统&#xff0c;实现社区生活缴费管理的信息化。则对于进一步提高社区生活缴费管理发展&#xff0c;丰富社区生活缴费管理经验能起到不少的促进…

【计算机网络】【常考问题总结】

1. ping 127.0.0.1 后会发生什么&#xff1f; ping 127.0.0.1 &#xff1b;ping 0.0.0.0 &#xff1b; ping localhost 面试官问&#xff1a;断网了&#xff0c;还能ping通 127.0.0.1 吗&#xff1f;为什么&#xff1f;_kevin_tech的博客-CSDN博客 2. MTU&#xff0c;MMU是…

探索线程池的威力:优化多线程任务管理与性能提升

比喻举例&#xff08;可以比作工人队伍&#xff09; 想象一下&#xff0c;如果我们需要完成很多工作&#xff0c;我们可以招募一群工人来协助。然而&#xff0c;如果每个工人都是临时招募的&#xff0c;工作完成后就解雇他们&#xff0c;那么每次都要花时间和精力来招募和解雇工…

CVPR2023论文及代码合集来啦~

以下内容由马拉AI整理汇总。 下载&#xff1a;点我跳转。 狂肝200小时的良心制作&#xff0c;529篇最新CVPR2023论文及其Code&#xff0c;汇总成册&#xff0c;制作成《CVPR 2023论文代码检索目录》&#xff0c;包括以下方向&#xff1a; 1、2D目标检测 2、视频目标检测 3、…

油画欣赏|《纯洁的梦乡》,心中的宇宙

《纯洁的梦乡》 80x60cm 陈可之2021年绘 油画《纯洁的梦乡》&#xff0c;以绮丽的想象&#xff0c;精湛的技艺&#xff0c;描绘出梦境中的蜻蜓、山、水、星空等事物&#xff0c;展现出一个纯洁美好的心灵宇宙世界。 油画采用水平构图的方式&#xff0c;在位置偏低的山脚设置水…

LeetCode--HOT100题(37)

目录 题目描述&#xff1a;104. 二叉树的最大深度&#xff08;简单&#xff09;题目接口解题思路代码 PS: 题目描述&#xff1a;104. 二叉树的最大深度&#xff08;简单&#xff09; 给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节点到最远…

全流程R语言Meta分析核心技术

Meta分析是针对某一科研问题&#xff0c;根据明确的搜索策略、选择筛选文献标准、采用严格的评价方法&#xff0c;对来源不同的研究成果进行收集、合并及定量统计分析的方法&#xff0c;最早出现于“循证医学”&#xff0c;现已广泛应用于农林生态&#xff0c;资源环境等方面。…

java 中的 JSP

程序框架 1. c/s框架&#xff1a; 通过客户端程序访问服务器 2.B/S框架 通过浏览器访问应用程序 &#xff1a;采用请求/相应模式进行交互 URL Tomcat服务器 1.开源项目 2.轻量级应用服务器 3.开源&#xff0c;稳定&#xff0c;资源占用小 Tomcat目录介绍 1.bin &#xff1a;存…

无涯教程-PHP - preg_match_all()函数

preg_match_all() - 语法 int preg_match_all (string pattern, string string, array pattern_array [, int order]); preg_match_all()函数匹配字符串中所有出现的模式。 它将按照您使用可选输入参数order指定的顺序将这些匹配项放置在pattern_array数组中。有两种可能的类…

EasyExcel 导出报空指针NullPointerException

java.lang.NullPointerException: null at sun.awt.FontConfiguration.getVersion(FontConfiguration.java:1264) at sun.awt.FontConfiguration.readFontConfigFile(FontConfiguration.java:219) 这是jdk缺少字体库问题 在官网也给出解决答案&#xff1a; 1.安装少了字体库…