【学习总结】《大话数据结构》- 第5章-串

【学习总结】《大话数据结构》- 总

第5章串-代码链接

启示:

  • 串(string)

    串是由零个或多个字符组成的有限序列,又名叫字符串。

目录

========================================

5.1 开场白

  • 一些可以略过的场面话...
  • 回文诗等引入字符串

========================================

5.2 串的定义

  • 串(string):由零个或多个字符组成的有限序列,又名叫字符串。

  • 相关概念:

    • 空格串:只包含空格的串。

      • 注意:与空串区别,空格串是有内容有长度的,而且可以不止一个空格

    • 子串:串中任意个数的连续字符组成的子序列,称为该串的子串。

      主串:相应地,包含子串的串,称为主串。

      • 子串在主串中的位置:子串的第一个字符在主串中的序号。

========================================

5.3 串的比较

  • 串的比较:通过组成串的字符之间的编码来进行的

    • 而字符的编码:指的是字符在对应字符集中的序号

  • ASCII 和 Unicode

    • ASCII码:用8为二进制数表示一个字符,总共可以表示256个字符

    • Unicode码:用16位二进制数表示一个字符,总共有216个字符,约65万多个字符

      (PS:两个字节应该是65000吧,怎么65万了???)

    • 为了和ASCII码兼容,Unicode码的前256个字符与ASCII码完全相同。

  • 串相等:长度相等,各个对应位置的字符相等。

  • 串的大小判断:

综上,即从第一个开始,分别遍历两串,当某i项不同时,可以分辨大小

========================================

5.4 串的抽象数据类型

  • 串与线性表的比较:

    • 线性表:更关注单个元素的操作,如查找一个元素,插入或删除一个元素

    • 串:更多是查找子串位置、得到指定位置子串、替换子串等操作



  • 举例一个Index操作的实现代码


========================================

5.5 串的存储结构

  • 串的存储结构与线性表类似,分为两类:顺序和链式

  • 串的顺序存储结构

    • 定义:用一组地址连续的存储单元来存储串中的字符序列。

    • 按照预定义大小,为每个定义的串分配一个固定长度的存储区,一般用定长数组来定义。

    • 一般可以将实际的串长值保存在数组的0下标位置,或者在数组的最后一个下标位置

    • 但有的语言规定在串值后面加一个不计入串长度的结束标记符号“\0”来表示串值的终结(但占用一个空间)

  • 由于过于不便,串的顺序存储操作有一些变化:串值的存储空间可在程序执行过程中动态分配而得

    比如堆:可由c语言动态分配函数malloc()和free()来管理

  • 串的链式存储结构

    • 若一个结点存放一个字符,会存在很大的空间浪费

    • 故串的链式可以一个结点放多个字符,最后一个结点若不满,可用#或其他非串值字符补全

  • 这里:一个结点存多少个字符才合适就变得很重要,会直接影响串处理的效率

  • 弊端:窜的链式除了连接两串操作方便,总的来说比如顺序存储灵活,性能也不如。

========================================

5.6 朴素的模式匹配算法

  • 模式匹配的定义:

    • 子串(又称模式串)的定位操作通常称做串的模式匹配,是串中最重要的操作之一。

    (比如:找一个单词在一篇文章中的定位问题,一篇文章相当于一个大字符串)

  • 朴素的匹配方法(BRUTE FORCE算法,BF算法):

    • 对主串的每个字符作为子串开头,与要匹配的字符串进行匹配

    • 对主串做大循环,每个字符开头做要匹配子串的长度的小循环,直到匹配成功或全部遍历完成为止

  • 图示:



  • 代码实现:

    (注:不考虑串的其他操作的代码,上一个Index代码中有多个其他操作)


  • 时间复杂度分析:

    • n:主串长度,m:要匹配子串长度

    • 最好情况:O(1) -- 第一次比较就找到

      • (没有循环,比较次数是子串长度值,是个常数)
    • 平均情况:O(n+m)

      • 根据等概率原则,平均是(n+m)/2次查找。
      • (严格讲,书中所举的例子,abcdegoogle匹配google,不是m+n,是(m-n)+n,不知道怎么就弄成m+n了。。)
    • 最坏的情况: O(m×n) (注:(n-m+1)×m)

      • 每遍比较都在最后出现不等,即每遍最多比较m次,最多比较n-m+1遍,总的比较次数最多为m(n-m+1)
    • <存疑,只有部分有m+n这个说法> 注:虽然,朴素的模式匹配,时间复杂度比较大,但是实际中,一般情况(除非模式串和主串之间存在很多的部分匹配的时候,因为此时每遍需要比较的次数很多,相乘不能近似),真正的执行时间是近似于 O(n+m) 的

========================================

5.7 KMP模式匹配算法

  • 引入:

    • KMP算法:由三位前辈发表的一个模式匹配算法,可以大大避免重复遍历的情况,称之为克努特-莫里斯-普拉特算法,检查KMP算法。

  • KMP算法原理

    • 主串S与模式串T有部分相同子串时,可以简化朴素匹配算法中的循环流程

    • 例子1:两串只有一部分相等时,S="abcdefgab", T="abcdex"




  • 例子2:两串有不止一部分相等时,S="abcabcabc", T="abcabx"



  • next数组

    • 定义:


  • 注:

    • 每次只先判断是否符合中间,并且只看1到j-1的串,并且只看前缀最长能和后缀重复的个数

    • 前后缀若有n个字符相等,k就是n+1

  • 例1:T="abcdex"


  • 例2:T="abcabx"


  • 例3:T="ababaaaba"


  • 例4:T="aaaaaaaab"



  • KMP模式匹配算法的代码实现

    • next数组

  • KMP算法


  • KMP算法的时间复杂度:O(m+n)

    • get_next的时间复杂度:O(m)

    • while循环的时间复杂度:O(n)

  • KMP算法的改进

  • 代码实现:


  • nextval数组值推导

    • 注:

      • 根据第j个的next值找它的next值x对应的第x个字符,并判断第j个和第x个字符是否相等

      • 若不相等,保持val值等于next值;若相等,val值等于第x个值的val值

  • 例1:T="ababaaaba"



  • 例2:T="aaaaaaaab"


========================================

5.8 总结回顾

  • 串定义

  • KMP算法

  • next数组和nextval数组常见考点

========================================

5.9 结尾语

  • 回文诗千古力作“璇玑图”666

END

posted @ 2019-07-26 17:34  anliux  阅读(817)  评论(0编辑  收藏  举报