数据结构:字符串

简介: 数据结构:字符串

1.字符串


字符串∶简称为串,是由零个或多个字符组成的有限序列。一般记为。


  • 字符串的长度︰字符串中字符的数目n称为字符串的长度。
  • 空串:零个字符构成的串也称为「空字符串」,它的长度为0,可以表示为" "。
  • 子串∶字符串中任意个连续的字符组成的子序列称为该字符串的「子串」。并且有两种特殊子串,起始于位置为0、长度为k的子串称为「前缀」。而终止于位置n -1、长度为k的子串称为「后缀」。
  • 主串:包含子串的字符串相应的称为「主串」。


举个例子:


str="Hello world"

在示例代码中,str是一个字符串的变量名称,Hello World则是该字符串的值,字符串的长度为11。该字符串的表示如下图所示∶

b04912d654ced83137512340547081cf_66e183803f9e70a8fc84ff89f8c0eb16.png


2.字符串的比较


2.1字符串的比较操作


字符串之间的大小取决于它们按顺序排列字符的前后顺序。比如字符串 str1 = "abc" 和 str2 = "acc",


它们的第一个字母都是 a,而第二个字母,由于字母 b 比字母 c 要靠前,所以 b < c,于是我们可以


说 "abc" < "acd" ,也可以说 str1 < str2。


字符串之间的比较是通过组成字符串的字符之间的「字符编码」来决定的。而字符编码指的是字符在对


应字符集中的序号。


对于两个不相等的字符串,我们可以以下面的规则定义两个字符串的大小:


  • 从两个字符串的第 0 个位置开始,依次比较对应位置上的字符编码大小。
  • 如果 str1[i] 对应的字符编码等于 str2[i] 对应的字符编码,则比较下一位字符。
  • 如果 str1[i] 对应的字符编码小于 str2[i] 对应的字符编码,则说明 str1 < str2。比如:"abc" <
  • "acc"。
  • 如果 str1[i] 对应的字符编码大于 str2[i] 对应的字符编码,则说明 str1 > str2。比如:"bcd" >
  • "bad"。
  • 如果比较到某一个字符串末尾,另一个字符串仍有剩余:
  • 如果字符串 str1 的长度小于字符串 str2,即 len(str1) < len(str2)。则 str1 < str2。比如:"abc" < "abcde"。
  • 如果字符串 str1 的长度大于字符串 str2,即 len(str1) > len(str2)。则 str1 > str2。比如:"abcde" > "abc"。
  • 如果两个字符串每一个位置上的字符对应的字符编码都相等,且长度相同,则说明 str1 == str2,比如:"abcd" == "abcd"。


按照上面的规则,我们可以定义一个 strcmp 方法,并且规定:


  • 当 str1 < str2 时,strcmp 方法返回 -1。
  • 当 str1 == str2 时,strcmp 方法返回 0。
  • 当 str1 > str2 时,strcmp 方法返回 1。


2.2字符串比较代码


def strcmp (str1, str2):
    index1, index2 = 0,0
    while index1< len(str1 ) and index2< len(str2):
        if ord(str1 [index1] )== ord(str2 [ index2 ]):
            index1 += 1
            index2 += 1
    elif ord(str1[ index1])< ord(str2 [index2]):
        return -1
    else:
        return 1
    if len (str1)< len(str2) :
        return-1
    elif len(str1)> len (str2):
        return 1
    else:
        return 0


2.3字符串的字符编码


以计算机中常用字符使用的 ASCII 编码为例。最早的时候,人们制定了一个包含 127 个字符的编码表


ASCII 到计算机系统中。ASCII 编码表中的字符包含了大小写的英文字母、数字和一些符号。每个字符


对应一个编码,比如大写字母 A 的编码是 65,小写字母 a 的编码是 97。后来又针对特殊字符,将


ASCII 扩展到了 256 位。


ASCII 编码可以解决以英语为主的语言,可是无法满足中文编码。为了解决中文编码,我国制定了


GB2312、GBK、GB18030 等中文编码标准,将中文编译进去。但是世界上有上百种语言和文字,各


国有各国的标准,就会不可避免的产生冲突,于是就有了 Unicode 编码。Unicode 编码最常用的就


是 UTF-8 编码,UTF-8 编码把一个 Unicode 字符根据不同的数字大小编码成 1 ~ 6 个字节,常用的


英文字母被编码成 1 个字节,汉字通常是 3 个字节。


2.4字符串的存储结构


字符串的存储结构跟线性表相同,分为「顺序存储结构」和「链式存储结构」。

63a19c782a182b08bda66ce17e821a98_1e4f25f11e71c137c955be295d14ed0f.png

dff6f0d616d90c6a481bfa0946b65c15_833c4a47b8f9b9e0b196b646ee83cf75.png


3.字符串匹配问题


字符串匹配:又称「模式匹配」。可以简单理解为,给定字符串 T 和 p,在主串 T 中寻找子串 p。主


串 T 又被称为「文本串」,子串 p 又被称为「模式串」。


在字符串问题中,最重要的问题之一就是字符串匹配问题。而按照模式串的个数,我们可以将字符串匹


配问题分为:「单模式串匹配问题」和「多模式串匹配问题」。


3.1单模式串匹配问题


单模式匹配问题︰给定一个文本串T = tt2….tn,再给定一个特定模式串p = PPp2..pn。要求从文本串T找出特定模式串p的所有出现位置。


根据在文本中搜索模式串方式的不同,可以将单模式匹配算法分为以下三种:


  • 基于前缀搜索方法∶在搜索窗口内从前向后(沿着文本的正向)逐个读入文本字符,搜索窗口中文本和模式串的最长公共前缀。著名的KMP算法和更快的 Shift-Or算法使用的就是这种方法。


  • 基于后缀搜索方法:在搜索窗口内从后向前(沿着文本的反向)逐个读入文本字符,搜索窗口中文本和模式串的最长公共后缀。使用这种搜索算法可以跳过一些文本字符,从而具有亚线性的平均时间复杂度。最著名的 BM 算法,以及 Horspool 算法、Sunday 算法都使用了这种方法。


  • 基于子串搜索方法:在搜索窗口内从后向前(沿着文本的反向)逐个读入文本字符,搜索满足「既是窗口中文本的后缀,也是模式串的子串」的最长字符串。与后缀搜索方法一样,使用这种搜索方法也具有亚线性的平均时间复杂度。这种方法的主要缺点在于需要识别模式串的所有子串,这是一个非常复杂的问题。Rabin-Karp 算法、BDM 算法、BNDM 算法 和 BOM 算法使用的就是这种思想。其中,Rabin-Karp 算法使用了基于散列的子串搜索算法。


3.2多模式串匹配问题


多模式匹配问题∶给定一个文本串,再给定一组模式串,其中每个模式串是定义在有限字母表上的字符串。要求从文本串T中找到模式串集合Р中所有模式串的所有出现位置。


模式串集合Р中的一些字符串可能是集合中其他字符串的子串、前缀、后缀,或者完全相等。解决多模式串匹配问题最简单的方法是利用「单模式串匹配算法」搜索r遍。这将导致预处理阶段的最坏时间复杂度为1440093905d165559707baf8b03b0be6_0b7d31e09a84727d00ad34df89cd0cf3.png,搜索阶段的最坏时间复杂度为1d4eeea55034caae5bee75ea3009012a_cd08d5533cfe935d4678670e9eeb952e.png


如果使用「单模式串匹配算法」解决多模式匹配问题,那么根据在文本中搜索模式串方式的不同,我们也可以将多模式串匹配算法分为以下三种∶


  • 基于前缀搜索方法∶搜索从前向后(沿着文本的正向)进行,逐个读入文本字符,使用在P上构建的自动机进行识别。对于每个文本位置,计算既是已读入文本的后缀,同时也是P中某个模式串的前缀的最长字符串。著名的AC自动机算法、Multiple Shift-And算法使用的这种方法。


  • 基于后缀搜索方法∶搜索从后向前(沿着文本的反向)进行,搜索模式串的后缀。根据后缀的下一次出现位置来移动当前文本位置。这种方法可以避免读入所有的文本字符。Set Horspool算法、wu-Manber算法使用了这种方法。


  • 基于子串搜索方法︰搜索从后向前(沿着文本的反向)进行,在模式串的长度为min(len(p'))的前缀中搜索子串,以此决定当前文本位置的移动。这种方法也可以避免读入所有的文本字符。Multiple BNDM算法、SBDM算法、SBOM算法都使用了这种方法。

目录
相关文章
|
22天前
|
XML JSON NoSQL
Redis的常用数据结构之字符串类型
Redis的常用数据结构之字符串类型
19 0
|
5月前
|
设计模式 算法 Java
【数据结构和算法】确定两个字符串是否接近
这是力扣的1657题,难度为中等,解题方案有很多种,本文讲解我认为最奇妙的一种。复杂度分析:时间复杂度:O(max⁡{n1,n2}+Clog⁡C),其中 n1 和 n2 分别是字符串 word1 和 word2 的长度,C=26 是字符集大小。空间复杂度:O(C)。
41 1
|
6月前
|
存储 算法 NoSQL
【霍罗维兹数据结构】多维数组 | 字符串 | 模式匹配
【霍罗维兹数据结构】多维数组 | 字符串 | 模式匹配
38 0
|
7月前
代码随想录Day9 栈与队列 LeetCodeT20 有效的括号 T1047 删除字符串中所有相邻重复项 T150 逆波兰表达式求值
代码随想录Day9 栈与队列 LeetCodeT20 有效的括号 T1047 删除字符串中所有相邻重复项 T150 逆波兰表达式求值
18 0
|
7天前
|
存储 NoSQL 安全
Redis入门到通关之数据结构解析-动态字符串SDS
Redis入门到通关之数据结构解析-动态字符串SDS
14 0
|
7天前
|
存储 安全 索引
Day5 长篇:字符串和常用数据结构
Day5 长篇:字符串和常用数据结构
5 0
|
16天前
|
Python
python学习-函数模块,数据结构,字符串和列表(下)
python学习-函数模块,数据结构,字符串和列表
59 0
|
16天前
|
索引 Python
python学习-函数模块,数据结构,字符串和列表(上)
python学习-函数模块,数据结构,字符串和列表
28 0
|
7月前
|
XML 存储 JavaScript
【JavaSE专栏89】Java字符串和XML数据结构的转换,高效灵活转变数据
【JavaSE专栏89】Java字符串和XML数据结构的转换,高效灵活转变数据
|
3月前
|
算法 Java 索引
数据结构之串—字符串而不是羊肉串
数据结构之串—字符串而不是羊肉串
36 0