「数据结构」串

串的定义和实现

串的定义

  1. 串: 即字符串,零个或多个字符组成的有限序列
  2. 串的长度:串中字符的个数n
  3. 空串:n=0时的串
  4. 子串:串中任意多个连续的字符组成的子序列
  5. 主串:包含子串的串
  6. 字符在主串中的位置:字符在串中的序号(从1开始)
  7. 子串在主串中的位置:子串的第一个字符在主串中的位置
  8. 空串和空格串
    1. M = ‘’ 是空串;
    2. N =’ ’ 是空格串;
  9. 串和线性表
    1. 串是特殊的线性表,数据元素之间呈线性关系
    2. 串的数据对象限定为字符集:中文字符、英文字符、数字字符、标点字符等
    3. 串的基本操作,如增删改除通常以子串为操作对象

串的存储结构

串的顺序存储

  1. 静态数组实现(定长顺序存储)
#define MAXLEN 255   //预定义最大串长为255typedef struct{char ch[MAXLEN];    //每个分量存储一个字符int length;        //串的实际长度
}SString;
  1. 动态数组实现(堆分配存储)
typedef struct{char *ch;    //按串长分配存储区,ch指向串的基地址int length;        //串的实际长度
}HString;
HString S;
S.ch = (char *) malloc(MAXLEN * szeof(char));    //用完要手动free
S.length = 0;
  1. 串长表示法
    1. 用一个额外的变量length来存放串的长度
    2. 用ch[0]充当length
      1. 优点:字符的位序和数组下标相同
      2. 缺点:字符串最大长度只有256
    3. 没有length变量,以字符 ‘\0’ 表示结尾(对应ASCII码的0)
      1. 缺点:需要从头到尾遍历
    4. ch[0]废弃不用,声明int型变量length来存放串的长度

基本操作实现

ch[0]废弃不用,声明int型变量length来存放串的长度

#define MAXLEN 255typedef struct{char ch[MAXLEN];   int length;       
}SString;// 求子串
bool SubString(SString &Sub, SString S, int pos, int len){//子串范围越界if (pos+len-1 > S.length)return false;for (int i=pos; i<pos+len; i++)Sub.cn[i-pos+1] = S.ch[i];Sub.length = len;return true;
}// 比较两个串的大小
int StrCompare(SString S, SString T){for (int i; i<S.length && i<T.length; i++){if(S.ch[i] != T.ch[i])return S.ch[i] - T.ch[i];}//扫描过的所有字符都相同,则长度长的串更大return S.length - T.length;
}// 定位操作
int Index(SString S, SString T){int i=1;n = StrLength(S);m = StrLength(T);SString sub;        //用于暂存子串while(i<=n-m+1){SubString(Sub,S,i,m);if(StrCompare(Sub,T)!=0)++i;else return i;    // 返回子串在主串中的位置}return 0;            //S中不存在与T相等的子串
}

串的链式存储

typedef struct StringNode{char ch;           //每个结点存1个字符struct StringNode *next;
}StringNode, * String;

缺点:存储密度低,每个字符1B,每个指针4B

  1. 改进方法
typedef struct StringNode{char ch[4];           //每个结点存多个个字符struct StringNode *next;
}StringNode, * String;

串的基本操作

  1. 假设有串 T = ‘’, S = ‘iPhone 11 Pro Max?’, W = ‘Pro’
    1. StrAssign(&T, chars): 赋值操作,把串T赋值为chars
    2. StrCopy(&T, S): 复制操作,把串S复制得到串T
    3. StrEmpty(S): 判空操作,若S为空串,则返回True,否则返回False
    4. StrLength(S): 求串长,返回串S的元素个数
    5. ClearString(&S): 清空操作,将S清为空串
    6. DestroyString(&S): 销毁串,将串S销毁(回收存储空间)
    7. Concat(&T, S1, S2): 串联联接,用T返回由S1和S2联接而成的新串———可能会导致存储空间的扩展
    8. SubString(&Sub, S, pos, len): 求子串,用Sub返回串S的第pos个字符起长度为len的子串
    9. Index(S, T): 定位操作,若主串S中存在与串T值相同的子串,则返回它再主串S中第一次出现的位置,否则函数值为0
    10. StrCompare(S, T): 串的比较操作,参照英文词典排序方式;若S > T,返回值>0; S = T,返回值=0 (需要两个串完全相同) ; S < T,返回值<0

串的模式匹配

  1. 字符串模式匹配:在主串中找到与模式串相同的子串,并返回其所在位置

简单的模式匹配算法

  1. 朴素模式匹配算法: 将主串中所有长度为m的子串依次与模式串对比,直到找到一个完全匹配的子串或所有的子串都不匹配为止
int Index(SString S, SString T){int i=1;                //扫描主串Sint j=1;                //扫描模式串Twhile(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;
}
  1. 时间复杂度分析
    1. 主串长度为n,模式串长度为m,大多数时候,n>>m
    2. 最多比较n-m+1个子串
    3. 最坏时间复杂度:每个子串都要对比m个字符(对比到最后一个字符才匹配不上),共要对比n-m+1个子串,复杂度 = O ( ( n − m + 1 ) m ) = O ( n m − m 2 + m ) = O ( n m ) O((n-m+1)m) = O(nm - m^2 + m) = O(nm) O((nm+1)m)=O(nmm2+m)=O(nm)
    4. 最好时间复杂度 = O(n)
    5. 每个子串的第一个字符就匹配失败,共要对比n-m+1个子串,复杂度 = O(n-m+1) = O(n)

串的模式匹配算法——KMP算法

  1. 根据模式串T,求出next数组,利用next数组进行匹配(主串指针不再回溯)
int Index_KMP(SString S, SString T, int next[]){int i=1;     //主串int j=1;     //模式串while(i<S.length && j<=T.length){if(j==0 || S.ch[i]==T.ch[j]){      //第一个元素匹配失败时++j;++i;         //继续比较后继字符}elsej=next[j]   //模式串向右移动}if(j>T.length)return i-T.length; //匹配成功
}
  1. 最坏时间复杂度:O(m+n)
    1. 求next数组时间复杂度O(m)
    2. 模式匹配过程最坏时间复杂度O(n)

求模式串的next数组

  1. next数组的作用:当模式串的第j个字符失配时,从模式串的第 next[j] 个字符继续往后匹配
  2. 任何模式串都一样,第一个字符不匹配时,只能匹配下一个子串,因此,next[1]都等于 0
  3. 任何模式串都一样,第2个字符不匹配时,应尝试匹配模式串的第1个字符,因此,next[2]都等于 1
  4. 在不匹配的位置前边,划一根分界线,模式串一步一步往后退,直到分界线之前“能对上”,或模式串完全跨过分界线为止,此时j指向哪儿,next数组值就是多少

KMP算法的进一步优化

  1. nextval[1]恒等于0
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];
}

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

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

相关文章

【Docker进阶】镜像制作-用Dockerfile制作镜像(一)

进阶一 docker镜像制作 文章目录 进阶一 docker镜像制作用dockerfile制作镜像dockerfile是什么dockerfile格式为什么需要dockerfileDockerfile指令集合FROMMAINTAINERLABELCOPYENVWORKDIR 用dockerfile制作镜像 用快照制作镜像的缺陷&#xff1a; 黑盒不可重复臃肿 docker…

嵌入式大厂面试题(1)—— CVTE

从本篇开始将会更新历年来各个公司的面试题与面经&#xff0c;题目来自于网上各个平台以及博主自己遇到的&#xff0c;如果大家有所帮助&#xff0c;帮忙点点赞和关注吧&#xff01; 岗位&#xff1a;嵌入式软件工程师。 面试时间&#xff1a;20分钟。 面试 1 、简历中写了做过…

Kafka 入门笔记

课程地址 概述 定义 Kafka 是一个分布式的基于发布/订阅模式的消息队列&#xff08;MQ&#xff09; 发布/订阅&#xff1a;消息的发布者不会将消息直接发送给特定的订阅者&#xff0c;而是将发布的消息分为不同的类别&#xff0c;订阅者只接受感兴趣的消息 消息队列 消息队…

HCIA-Datacom实验指导手册:4.3 实验三:网络地址转换配置实验

HCIA-Datacom实验指导手册&#xff1a;4.3 实验三&#xff1a;网络地址转换配置实验 一、实验介绍&#xff1a;二、 思考题与附加内容 一、实验介绍&#xff1a; NAT的作用&#xff1a; 1、很大程度提高网络安全性。 2、控制内外网网络联通性问题。 特点&#xff1a; 1&#…

JDK 11 vs JDK 8:探索Java的新特性和改进

随着技术的不断进步&#xff0c;Java开发工具包&#xff08;JDK&#xff09;也在不断演变&#xff0c;为开发者带来更高效、更安全的编程体验。在这篇文章中&#xff0c;我们将重点探讨JDK11相较于JDK 8所引入的一些新特性和改进&#xff0c;以便您能够更好地了解Java的最新发展…

leetcode:买卖股票最佳时机二

思路&#xff1a; 使用贪心算法&#xff1a;局部最优是将买卖过程中产生的正数进行相加&#xff0c;进而使得最后结果最大&#xff08;全局最优&#xff09;。 price [7,1,5,10,3,6,4] -6,4,5,-7,3,-2 正数相加就得到了最大 代码实现&#xff1a; 1.循环中下标从1开始 …

大数据的基础探索之大数据时代

前言&#xff1a;大数据已经是大势所趋&#xff0c;在这个网络时代能够不断地整合资源的人本身也是一种能力拥有者&#xff0c;在这个时代&#xff0c;如果一个人可以掌握数据分析工具&#xff0c;利用好云计算的能力&#xff0c;对于自己的个人而言来说都是一个极其重要的参与…

【PyTorch】张量(Tensor)的生成

PyTorch深度学习总结 第一章 Pytorch中张量(Tensor)的生成 文章目录 PyTorch深度学习总结一、什么是PyTorch&#xff1f;二、张量(Tensor)1、张量的数据类型2、张量生成和信息获取 总结 一、什么是PyTorch&#xff1f; PyTorch是一个开源的深度学习框架&#xff0c;基于Python…

20240212请问如何将B站下载的软字幕转换成为SRT格式?

20240212请问如何将B站下载的软字幕转换成为SRT格式&#xff1f; 2024/2/12 12:47 百度搜索&#xff1a;字幕 json 转 srt json srt https://blog.csdn.net/a_wh_white/article/details/120687363?share_token2640663e-f468-4737-9b55-73c808f5dcf0 https://blog.csdn.net/a_w…

上位机图像处理和嵌入式模块部署(利用python开发软件)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 开发windows和linux软件的时候&#xff0c;大家一般都是习惯于用c/c语言进行开发&#xff0c;但是目前来说很多的开发板都是支持python语言开发的。…

RK3588平台开发系列讲解(视频篇)RKMedia 数据流向

文章目录 一、 获取RKMedia模块通道中的数据二、RKMedia的数据源和接收者三、模块通道绑定API调用 沉淀、分享、成长&#xff0c;让自己和他人都能有所收获&#xff01;&#x1f604; &#x1f4e2;RKMedia是RK提供的一种多媒体处理方案&#xff0c;可实现音视频捕获、音视频输…

服务治理中间件-Eureka

目录 简介 搭建Eureka服务 注册服务到Eureka 简介 Eureka是Spring团队开发的服务治理中间件&#xff0c;可以轻松在项目中&#xff0c;实现服务的注册与发现&#xff0c;相比于阿里巴巴的Nacos、Apache基金会的Zookeeper&#xff0c;更加契合Spring项目&#xff0c;缺点就是…

前端vue 数字 字符串 丢失精度问题

1.问题 后端返回的数据 是这样的 一个字符串类型的数据 前端要想显示这个 肯定需要使用Json.parse() 转换一下 但是 目前有一个问题 转换的确可以 showId:1206381711026823172 有一个这样的字段 转换了以后 发现 字段成了1206381711026823200 精度直接丢了 原本的数据…

MySQL监控Innodb信息

Innodb监控 Innodb由于支持事务操作&#xff0c;是mysql中使用最多的存储引擎&#xff0c;所以如何监控Innodb存储引擎以进行性能优化是在使用mysql过程中遇到最多的&#xff0c;那么如何进行监控呢&#xff1f; show engine -- 显示innodb存储引擎状态的统计和配置信息show en…

MogaNet实战:使用MogaNet实现图像分类任务(一)

文章目录 摘要安装包安装timm 数据增强Cutout和MixupEMA项目结构计算mean和std生成数据集 摘要 论文&#xff1a;https://arxiv.org/pdf/2211.03295.pdf 作者多阶博弈论交互这一全新视角探索了现代卷积神经网络的表示能力。这种交互反映了不同尺度上下文中变量间的相互作用效…

C语言函数指针实现函数参数化

之前学习了基本的函数指针;函数指针有多种用途;下面看一下函数参数化; 函数参数化是指通过函数指针将函数的某些行为参数化。这样可以在调用函数时动态地指定函数的行为。 新建一个单文档工程;下述增加的函数声明加到视类cpp文件的头部,函数体加到视类cpp文件的尾部,在…

时域和离散域的重要转换器

自然界的模拟信号都是连续信号&#xff0c;也就是我们常说的时域信号&#xff0c;而我们的计算机只能处理离线的数字量信号&#xff0c;但是我们的闭环控制系统都是由离散域和时域所组成的&#xff0c;这里的离散域包括我们的计算机微控制器&#xff0c;时域包括我们的被控对象…

2024.2.3 作业

1、实现单向循环链表的头插头删尾插尾删 #include<stdio.h> #include<string.h> #include<stdlib.h> typedef int datatype; typedef struct node {//数据域int data;//指针域struct node *next; }*Linklist; Linklist create() {Linklist s(Linklist)mallo…

linux应用 进程间通信之信号量(POSIX)

1、前言 1.1 定义 POSIX信号量是一种用于同步进程之间对共享资源访问的机制。它允许进程在访问共享资源之前进行互斥和同步操作&#xff0c;以确保数据的一致性和正确性。POSIX信号量通常由一个整数值表示&#xff0c;可以进行原子增减操作&#xff0c;以及等待和通知操作。 …

【Python网络编程之DHCP服务器】

&#x1f680; 作者 &#xff1a;“码上有前” &#x1f680; 文章简介 &#xff1a;Python开发技术 &#x1f680; 欢迎小伙伴们 点赞&#x1f44d;、收藏⭐、留言&#x1f4ac; Python网络编程之DHCP服务器 代码见资源&#xff0c;效果图如下一、实验要求二、协议原理2.1 D…