数据结构——串(字符串)
文章目录
- **一 串的定义和实现**
- **1 定义**
- **2 串的存储结构**
- **2.1 定长顺序存储表示**
- **2.2 堆分配存储表示**
- **2.3 块链存储表示**
- **3 串的基本操作**
- **二 串的模式匹配**
- **1 简单的模式匹配算法**
- **==2 串的模式匹配算法——KMP算法==**
- **2.1 字符串的前缀,后缀和部分匹配值**
- **2.2 KMP算法的原理**
- **2.3 KMP算法的优化**
一 串的定义和实现
1 定义
串是由零个或多个字符组成的有限序列,可以是字母,数字或者其他字符
由一个或多个空格组成的串称为空格串(空格也是一种符号)
如“hello world 232@#%^&”
2 串的存储结构
2.1 定长顺序存储表示
#define maxline 255
typedef struct
{char ch[maxline];int length;
}Sstring;
一组连续的存储单元
超过的长度会发生截断;一般字符串的结尾都有一个隐含的“\0”,不计入长度
2.2 堆分配存储表示
仍是一组连续的存储单元,但是存储空间是执行过程中动态分配的
typedef struct
{char *ch;int length;
}Hstring;
2.3 块链存储表示
每个结点可以存放一个字符,也可以存放多个字符
每个结点称为块,整个链表称为块链结构
最后一个结点占不满时通常用#补上
3 串的基本操作
Strassign(&T,chars); \\T赋值到chars
Strcopy(&T,S); \\S复制到T
Strempty(S); \\判空
Strcompare(S,T); \\比较ST,S>T返回值大于0
Strlength(S); \\求串长
Substring(&Sub,S,pos,len); \\用sub返回s从pos位置长度为len的子串
Concat(&T,S1,S2); \\T返回s1和s2的串接
Index(S,T); \\若S中存在T相同的子串,返回第一次出现的位置,否则为0
Clearstring(&S); \\清空
Destroystring(&S); \\销毁
二 串的模式匹配
1 简单的模式匹配算法
模式匹配:子串的定位操作,求的是子串在主串中的位置
采用定长顺序存储结构
暴力算法:
int Index(Sstring S,Sstring R)
{int i =1,j=1;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; \\找到了位置并返回elsereturn 0; \\没找到
}
时间复杂段:O(mn),m,n分别是子串和主串的长度
算法思想:主串和子串的字符一一对比,如果不对,子串倒退到一开始,主串倒退到刚刚比较的的下一个位置
当子串为“00001”,主串为“0000000000000000000000001”时,可以预想到查找效率极低,需要匹配到最后一个位置才能找到
2 串的模式匹配算法——KMP算法
从刚刚的例子可以看出第四次和第五次是不需要进行的,因为从第三次的结果可以看出“b” “c” “a”是无需进行比较的,仅需向右滑动三个位置
如果已匹配相等的前缀序列中有某个后缀正好是子串的前缀,那么就可以将子串向后滑动到与这些相等字符对齐的位置
2.1 字符串的前缀,后缀和部分匹配值
前缀:除最后一个字符意外,字符串的所有头部子串
后缀:除第一个字符外,字符串的所有尾部子串
部分匹配值:字符串的前缀和后缀的最长相等前后缀长度,以下记为PM
‘a’:前后缀为空,PM=0
‘ab’:前缀‘a’,后缀‘b’,‘a’ ⋂ \bigcap ⋂‘b’= ∅ \varnothing ∅,PM=0
‘aba’,前缀‘a,ab’,后缀‘a,ba’,并集为‘a’,PM=1
‘abab’,前缀‘a,ab,aba’,后缀‘b,ab,bab’,并集‘ab’,PM=2
‘ababa’,前缀‘a,ab,aba,abab’,后缀‘a,ba,aba,baba’,并集‘a,aba’,PM=3
所以‘ababa’的部分匹配值为00123
那么刚刚例子中abcac的PM就为
编号 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|
S | a | b | c | a | c |
PM | 0 | 0 | 0 | 1 | 0 |
采用PM的移动算法:
移动位数 = 已匹配的字符数 - 最后一个匹配成功的字符对应的PM
主串没有回退,时间复杂度:O(n+m),大大提高了效率
2.2 KMP算法的原理
通过上述的部分匹配值可以得出匹配失败时主串对比的移动位数
写成式子:move=(j-1)-PM[j-1]
但是失败时总是去找匹配失败的上一个PM值,使用起来不太方便,所有将所有PM表右移一位,得到next数组:
编号 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|
S | a | b | c | a | c |
PM | -1 | 0 | 0 | 0 | 1 |
第一个元素右移后用-1来填充,因为若是第一个元素匹配失败,只需要将子串向右移动一位再比较,不需要计算子串移动的位数
最后一个元素溢出,但上一个PM本来就是计算下一个元素的,所有这个PM不存在下一个元素,可以舍弃
移动位数:move = (j-1) - next[j]
所以指针J回退的位置:j=j-move=next[j]+1
为了再使得公式简单简洁,再把next数组整体+1
编号 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|
S | a | b | c | a | c |
PM | 0 | 1 | 1 | 1 | 2 |
最终的子串指针变化公式j=next[j]
next[j]的含义:在子串的第j个字符与主串发生失配时,则跳到子串的next[j]位置重新与主串当前位置进行比较
怎么推理next数组的一般公式?
假设主串为S1S2……Sn,模式串为p1p2……pm,当主串的第i个字符与模式串的第j个字符失配,子串应向右滑动多远,然后与模式串的那个字符比较?
假设此时应该与第k(k<j)个字符继续比较,则模式串的前k-1个字符的子串必须满足下列条件,且不可能存在k,>k满足下列条件
‘p1p2……pk-1’=‘ pj-k+1pj-k+2……pj-1’
(1)若满足上述条件,失配时,将模式向右滑动至模式中第k个字符和主串第i个字符对齐,此时模式中前k-1个字符的子串必定与主串中第i个字符之前长度为k-1的子串相等,只需从模式第k个字符与主串第i个字符继续比较即可
(2)不满足上述条件时(k=1),直接将模式串右移j-1位,让主串的第i个字符与模式串第一个字符对比,此时右移位数最大
(3)若模式串的第一个子串就与主串的第i个字符失配时,规定next[1]=0;模式串右移一位,从主串的下一个位置i+1与模式串的第一个位置继续对比
即next函数的公式为
首先可知next[1]=0,next[j]=k;那next[j+1]为多少呢,有两种情况:
(1)若pk=pj,则满足条件 ‘p1p2……pk-1’=‘ pj-k+1pj-k+2……pj-1’ ,所以next[j+1]=k+1,即next[j+1]=next[j]+1
(2)若pk ≠ \neq =pj,不满足上述条件,则把p1…pk向右滑动到next[k]与pj比较,若pnext[k]与pj还是不匹配,继续找更短的相等前后缀,继续用pnext[next[k]]比较,直到更小的k’满足条件,next[j+1]=k’+1;如果不存在k,则令next[j+1]=1
举例说明:
j | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
---|---|---|---|---|---|---|---|---|---|
模式 | a | b | a | a | b | c | a | b | a |
next[j] | 0 | 1 | 1 | 2 | 2 | 3 | 1 | 2 | 3 |
j=1:初始next[1]=0
j=2:往前不存在p0与p1相等,则next[2]=1
j=3:往前不存在p与p2相等,则next[3]=1
j=4:通过p3的next判断pnext[3]即p1=p3,则next[4]=next[3]+1=2,同时也是next[4]=k+1=2
j=5:通过pnext[next[4]]即p1=p4,则k=next[next[4]]=1,next[5]=k+1=2
j=6:p5=pnext[2],则k=2,next[6]=k+1=3
j=7:不存在p与p6相等,则next[7]=1
j=8:p7=p1,则k=1,next[8]=1+1=2
j=9:p8=p2,则k=2,next[9]=2+1=3
代码如下
void getnext(Sstring T,int next[])
{int i =1,j=0;next[1]=0;while(i<T.length){if(j==0||T.ch[i]==T.ch[j]){i++;j++;next[i]=j;}elsej = next[j];}}int IndexKMP(Sstring S,Sstring T,int next[])
{int i =1,j=1;while(i<=S.length && j<= T.length){if(j==0||S.ch[i]==T.ch[j]){i++;j++;}else{j=next[j];}}if(j>T.length){return i-T.length;}else{return 0;}
}
2.3 KMP算法的优化
前面的next数组仍有缺项,比如‘aaaab ’和‘aaabaaaab’ 匹配时
不应该出现pj=pnext[j],当pj ≠ \neq =sj时,下次匹配必然还是pnext[j]与sj比较,毫无意义
如果出现pj=pnext[j],需要再次递归,将next[j]修正为next[next[j]],直到不相等,新数组命名为nextval
void getnextval(Sstring T,int nextval[])
{int i =1,j=0;nextval[1]=0;while(i<T.length){if(j==0||T.ch[i]==T.ch[j]){i++;j++;if(T.ch[i]!=T.ch[j])nextval[i]=jelsenextval[i]=nextval[j];}elsej = nextval[j];}}
相关文章:
数据结构——串(字符串)
文章目录 **一 串的定义和实现****1 定义****2 串的存储结构****2.1 定长顺序存储表示****2.2 堆分配存储表示****2.3 块链存储表示** **3 串的基本操作** **二 串的模式匹配****1 简单的模式匹配算法****2 串的模式匹配算法——KMP算法****2.1 字符串的前缀,后缀和…...
Seata服务端的启动过程 学习记录
1.ServerRunner ServerRunner类实现了CommandLineRunner与DisposableBean接口,将会在Spring容器启动和关闭的时间,分别执行 run 和 destory 方法。 而seata服务端的启动过程,都藏在run方法中 2.整体流程 io.seata.server.Server#start pu…...
Log4J
引言 为什么要用日志? --> 方便调试代码 什么时候用?什么时候不用? 出错调试代码时候用 生产环境下就不需要,就需要删除 怎么用? --> 输出语句 一、Log4J 1.1 介绍 log4j是Apache的一个开放源代码的项目,通过使用log4j,我们可以控…...
【零基础学机器学习 5】机器学习中的分类:什么是分类以及分类模型
👨💻 作者简介:程序员半夏 , 一名全栈程序员,擅长使用各种编程语言和框架,如JavaScript、React、Node.js、Java、Python、Django、MySQL等.专注于大前端与后端的硬核干货分享,同时是一个随缘更新的UP主. 你可以在各个…...
目标检测算法:Faster-RCNN论文解读
目标检测算法:Faster-RCNN论文解读 前言 其实网上已经有很多很好的解读各种论文的文章了,但是我决定自己也写一写,当然,我的主要目的就是帮助自己梳理、深入理解论文,因为写文章,你必须把你所写的东西表…...
基于Python的接口自动化-Requests模块
目录 引言 一、模块说明 二、Requests模块快速入门 1 发送简单的请求 2 发送带参数的请求 3 定制header头和cookie 4 响应内容 5 发送post请求 6 超时和代理 三、Requests实际应用 引言 在使用Python进行接口自动化测试时,实现接口请求…...
Vue框架中监测数组变化的方法
在 Vue 中,如果直接对数组进行操作,比如使用下标直接修改元素,数组长度不变时, Vue 是无法监测到这种变化的,导致无法触发视图更新。针对该问题,总结如下解决方法: 一、使用 Vue.js 提供的方法…...
PHP isset()函数使用详解,PHP判断变量是否存在
「作者主页」:士别三日wyx 「作者简介」:CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」:对网络安全感兴趣的小伙伴可以关注专栏《网络安全入门到精通》 isset 一、判断变量是否存在二、判断变量是否为NUL…...
2021~2022 学年第二学期《信息安全》考试试题(A 卷)
北京信息科技大学 2021~2022 学年第二学期《信息安全》考试试题(A 卷) 课程所在学院:计算机学院 适用专业班级:计科1901-06,重修 考试形式:(闭卷) 一、选择题(本题满分10分,共含10道小题,每小题…...
通俗讲解元学习(Meta-Learning)
元学习通俗的来说,就是去学习如何学习(Learning to learn),掌握学习的方法,有时候掌握学习的方法比刻苦学习更重要! 下面我们进行详细讲解 1. 从传统机器学习到元学习 传统的机器学中,我们选择一个算法&…...
生成全球定位系统、伽利略和北斗二号的Matlab代码及实际数据捕获文件,为测试功能提供完整信号与频谱
使用Matlab生成和分析GNSS信号(第一部分) 全球导航卫星系统(Global Navigation Satellite System, GNSS)是一个提供全球覆盖的,定位、导航、时间传递服务的系统。由全球定位系统(GPS),俄罗斯的格洛纳斯(GLONASS),欧洲…...
Android 14 版本变更总览
Android 14 版本 Android 14 总览Android 14 功能和变更列表行为变更:所有应用行为变更:以 Android 14 或更高版本为目标平台的应用功能和 API 概览 Android 14 总览 https://developer.android.google.cn/about/versions/14?hlzh-cn 文章基于官方资料…...
内网安全:Cobalt Strike 工具 渗透多层内网主机.(正向 || 反向)
内网安全:Cobalt Strike 工具 渗透多层内网主机. Cobalt Strike 是一款以 metasploit 为基础的 GUI 的框架式渗透工具,又被业界人称为 CS。拥有多种协议主机上线方式,集成了端口转发,服务扫描,自动化溢出,…...
ChatGPT 五个写论文的神技巧,让你的老师对你刮目相看!
导读:ChatGPT这款AI工具在推出两个月内就累积了超过1亿用户。我们向您展示如何使用ChatGPT进行写作辅助,以及其他一些有用的写作技巧。 本文字数:2000,阅读时长大约:12分钟 ChatGPT这款AI工具在推出两个月内就累积了超…...
模型服务文档自动生成,要素追溯关联、结构规范易读|ModelWhale 版本更新
整装待发的初夏,ModelWhale 持续聚焦 AI for Science,针对大模型等前沿带来了新一轮的版本更新,期待为你提供更好的使用体验。 本次更新中,ModelWhale 主要进行了以下功能迭代: • 新增 模型服务文档自动生成…...
《微服务实战》 第三十一章 ShardingSphere - ShardingSphere-JDBC
前言 Apache ShardingSphere 是一款分布式的数据库生态系统, 可以将任意数据库转换为分布式数据库,并通过数据分片、弹性伸缩、加密等能力对原有数据库进行增强。 Apache ShardingSphere 设计哲学为 Database Plus,旨在构建异构数据库上层的…...
【论文阅读】Twin neural network regression is a semi- supervised regression algorithm
论文下载 GitHub bib: ARTICLE{,title {Twin neural network regression is a semi- supervised regression algorithm},author {Sebastian J Wetzel and Roger G Melko and Isaac Tamblyn},journal {Machine Learning: Science and Technology},year {2022},volum…...
java之反射机制和注解(更新中......)
Reflect在文档中的位置: 文档链接:https://docs.oracle.com/javase/8/docs/api/index.html 用于获取类或对象的反射信息。 常用的反射机制重要的类: java.lang.Class:整个字节码,代表一个类型。包含了以下三块内容&a…...
【Unity入门】25.入门结课Demo--神鸟大战怪兽
【Unity入门】入门结课Demo--神鸟大战怪兽 大家好,我是Lampard~~ 欢迎来到Unity入门系列博客,所学知识来自B站阿发老师~感谢 (一) 前言 经过了两个月的学习,我们也顺利的完成了入门课程,最后就用一个Demo作为我们的结课句号吧&am…...
HTTP协议基本格式
HTTP即HyperText Transfer Protocol(超文本传输协议),HTTP基于TCP/IP协议传输数据。 目录 Chrome抓包Fiddler代理抓包HTTP协议格式HTTP请求首行URL方法Get方法Post方法Get与Post的区别 请求报头中的属性Cookie和SessionCookie与Session的区别…...
在 ubuntu 22.04 上配置界面服务器 xrdp
文章目录 图形界面解决方案VNCXRDP XRDP 实例安装和配置使用 XRDP 使用原理谁更快 : X11转发 > XRDP > VNC 图形界面解决方案 1. VNC 2. XRDP 3. X11 ssh : // https://blog.csdn.net/u011011827/article/details/131065690VNC 外部开放端口 用的 是 5901-5910 桌面用…...
53、基于51单片机蓄电池充电器过充过放保护LCD液晶屏显示系统设计(程序+原理图+PCB源文件+参考论文+参考PPT+元器件清单等)
方案选择 单片机的选择 方案一:AT89C52是美国ATMEL公司生产的低电压,高性能CMOS型8位单片机,器件采用ATMEL公司的高密度、非易失性存储技术生产,兼容标准MCS-51指令系统,片内置通用8位中央处理器(CPU)和Flash存储单元&…...
【C/C++】详解 函数重载和应用
创作不易,本篇文章如果帮助到了你,还请点赞 关注支持一下♡>𖥦<)!! 主页专栏有更多知识,如有疑问欢迎大家指正讨论,共同进步! 🔥c系列专栏:C/C零基础到精通 🔥 给大…...
WPF开发txt阅读器4:字体控件绑定
文章目录 控件折叠字体尺寸绑定选择字体字体的中文名称 txt阅读器系列: 需求分析和文件读写目录提取类💎列表控件与目录 控件折叠 作为一个txt阅读器,至少能够设置文字字体、尺寸,段落行间距等,还得有护眼模式等一系…...
CoreDX DDS应用开发指南(8)开发订阅应用程序
11 应用数据类型Application Data Types 11.1 概述 每个DDS主题都包含一个且仅包含一个数据类型,这是在主题上进行通信时使用的用户定义的数据类型。在大多数情况下,应用程序开发人员以数据定义语言(DDL)格式定义这些DDS数据类型。编译器用于将这些DDL类型定义转换为适当的…...
基于Python的接口自动化-读写配置文件
目录 引言 configparser模块功能介绍 引言 在编写接口自动化测试脚本时,有时我们需要在代码中定义变量并给变量固定的赋值。为了统一管理和操作这些固定的变量,咱们一般会将这些固定的变量以一定规则配置到指定的配置文件中,后续需要用到这…...
useEffect的基础知识和底层机制
useEffect 是 React 中一个重要的 Hook,用来处理组件的副作用操作。它的基础知识包括两个方面:执行时机和参数。 执行时机: useEff ect 的执行时机包括两种情况: 组件挂载时,即第一次渲染之后。组件更新时ÿ…...
chatgpt赋能python:Python中如何加空格
Python中如何加空格 Python是一门广泛应用于科学计算、数据分析、人工智能、Web开发等领域的高级编程语言。在Python编程过程中,经常需要使用到空格,以实现程序的格式化和美观,同时也有助于提高代码的可读性和可维护性。本文主要介绍Python中…...
软件测试之路已不再是坦途
去年下半年才跳了槽,过程非常顺利,没有经历大家所说的工作荒的境地,所以一直没有直观地感受到软件测试就业形势到底有多严峻。 近来看到一些机构频频发出某某测试员在糟糕的就业形势下逆袭拿下XXW的某厂offer,然后推荐测试进阶课…...
扫雷——C语言实现
扫雷 文章目录 扫雷实现代码什么是扫雷基本功能实现显示选择菜单定义几个二维数组?确定数组大小初始化数组布置地雷打印展示数组排查地雷记录指定区域周围地雷的个数判断排雷成功排查地雷实现代码 基本功能的实现代码和效果展示 拓展功能简化游戏界面改变字体颜色实…...
沈阳网站建设搜q479185700/百度资源共享链接分享组
开发四年只会写业务代码,分布式高并发都不会还做程序员? 目前,Mozilla 已将 Firefox 的其余 Firefox Test Pilot 扩展从 Test Pilot 网站迁移至 Mozilla AMO(Mozilla 官方插件网站)。这标志着 Firefox Test Pilot 计…...
wordpress外网ip访问不了/个人网站源码免费下载
Session 用于保存每个用户的专用信息. 每个客户端用户访问时,服务器都为 每个用户分配一个唯一的会话 ID(Session ID) . 她的生存期是用户持续请求时 间再加上一段时间(一般是 20 分钟左右).Session 中的信息保存在 Web 服务器内 容中,保存的数据量可大可…...
湖南网站建设企业/关键词优化师
const readline require(readline-sync);//引入用户输入功能console.log(请输入数组的长度:);//提示用户输入let length readline.question();//获取用户输入let arr [];//创建数组for (let i 0; i < length; i) {console.log(请输入数组的第${i 1}个数&…...
深圳独立站建站/58精准推广点击器
1、SpringMVC 中的Interceptor 拦截请求是通过HandlerInterceptor 来实现的。在SpringMVC 中定义一个Interceptor 非常简单,主要有两种方式,第一种方式是要定义的Interceptor类要实现了Spring 的HandlerInterceptor 接口,或者是这个类继承实现…...
怎么建立一个网站搜关键词会跳出/怎么制作网页里面的内容
. 参数 主参数 KO 设置此参数为元素的 value 值。之前的值将被覆盖。 如果参数是监控属性 observable 的,那元素的 value 值将根据参数值的 变化而更新,如果不是,那元素的 value 值将只设置一次并且以后不在更新。 如果…...
做个网站找别人做的吗/自己建网站怎么推广
直接上代码,其中有的c和c混乱的地方,在vs2008下.cpp文件测试通过。 #include <stdio.h> #include <stdlib.h>//从节点cur开始向下成调整部分大根堆 //len为数组长度,数组下标从0开始 template<typename T> void heap_adjus…...