邓公数据结构与算法 第十三章 串

  • ADT
    • 定义和特点
    • 术语
    • ADT接口实现
  • 模式匹配
    • 问题与需求
    • 算法测试方法
  • 蛮力匹配
    • 构思
    • 蛮力匹配:版本1
    • 蛮力匹配:版本2
    • 蛮力匹配:性能分析
  • KMP算法
    • next【】表
    • 理解next【】表
    • 构造next【】表
    • next【】表代码实现
    • KMP复杂度准确分析 ——线性时间O(n)
    • KMP算法改进版
  • BM_BC算法
    • 动机——bc【】表
    • 坏字符
    • 构造bc【】
    • 最好情况—— O(n/m)
    • 最坏情况—— O(n*m)
  • BM_GS算法
    • 好后缀策略
      • 概念
      • 实例
      • 构造GS表
      • 性能
    • Karp-Rabin 算法:串即是数
      • 凡物皆数
      • 串亦是数
      • 数位溢出
      • 散列压缩
      • 散列冲突
      • 快速指纹计算

ADT

定义和特点

特点:串长远远大于字符种类

术语

ADT接口实现

模式匹配

问题与需求

主要解决4个问题。

算法测试方法

成功与失败的情况分开来测试。

蛮力匹配

构思

  • 自左向右,以字符为单位,依次移动模式串直到在某个位置发现匹配

蛮力匹配:版本1

  • return i-j

i-j 大于n-m 即可判定失败。因为失败时 (字符串T)i=n,(模板串P)j<m。
i-j<=n-m 即可判定成功
i-j的意义是字符串中与模板串开始比较的位置。

蛮力匹配:版本2


上述算法有个细节

if( m <= j ) break;

直接跳出当前for(i。。。。i++)的循环,而 当前循环的i 加1操作没有执行!
当返回值 i = n - m 时配对成功,当 i =n - m + 1 时配对失败

蛮力匹配:性能分析

  1. 最好最坏情况复杂度分析

  1. 最坏情况例子

字母表={0,1}
成功次数m-1次,失败次数1

  1. 特点

  2. 蛮力算法为何低效

  • 有重复匹配的前缀:即一个字符串T中的一个位置需要比对多次。
  • 不变性:模板P总是右移一位去比对。不会根据情况改变

KMP算法

next【】表

理解next【】表

理解N ( p , j )={ 0 <= t<j | P [ 0, t ) == P[ j-t , j ) };

  1. 具有特点:
    快速右移
    避免回溯
    next【0】=-1

构造next【】表

next【j】的意思感觉下图说的不对,应该是最大自匹配的真前缀和真后缀的长度减1

  1. 当p【j】== p【 next [ j ] 】

计算next【j+1】

  1. 当p【j】!= p【 next [ j ] 】时

next【】表代码实现

KMP复杂度准确分析 ——线性时间O(n)

设一个k=2i-j (分析方法忽略吧)

KMP算法改进版

改进的原因:在当前模式串P的元素重复,使得连续与文本串T的元素进行对比失败,产生冗余,故可跳过相同元素与T的重复比对,提高KMP算法性能

BM_BC算法

动机——bc【】表

因为字符串配对过程中,大部分情况失败的概率远远大于成功的概率,故可采用bc表。next表善于利用配对成功的字符(经验),而bc表 注重配对失败的教训可以帮助我们排除更多字符。

坏字符

  • 如何右移
    试图从模式串P中找到一个X(与文本串T相同的X),使这个X能与T中的X对齐。P串偏移的距离存入bc【】表中。

  • 偏移距离如何确定
    位移量取决于适配位置 j,以及X在模式串P中的秩,而与T和i无关。

    • 由此引申因偏移距离确定发生的三种情况

    1. 从模式串P中能找到一个或多个X(与文本串T相同的X) , 要位移量尽可能小,则要选择模式串P中X的 秩最大的(也可以说从最大秩开始 后面没有X了)且偏移量 j - bc [ ’ X ’ ] >0
    2. 从模式串P中不能找到一个X(与文本串T相同的X),则通过最左侧哨兵通配符" * ",将模式串P完整的移过X(文本串T中的X)这个位置。
    3. 虽然从模式串P找到X 但X过于靠右即秩过大,会造成偏移量 j - bc [ ’ X ’ ] <0 ,故只需将模式串P 向后一个位置。

构造bc【】

画家策略:模式串P中自左向右,每次出现对应的字符则更新最大秩

/*DSA*/#include "string_pm/string_pm_test.h"//*****************************************************************************************
//    0                       bc['X']                                m-1
//    |                       |                                      |
//    ........................X***************************************
//                            .|<------------- 'X' free ------------>|
//*****************************************************************************************
int* buildBC ( char* P ) { //构造Bad Charactor Shift表:O(m + 256)int* bc = new int[256]; //BC表,与字符表等长for ( size_t j = 0; j < 256; j ++ ) bc[j] = -1; //初始化:首先假设所有字符均未在P中出现for ( size_t m = strlen ( P ), j = 0; j < m; j ++ ) //自左向右扫描模式串Pbc[ P[j] ] = j; //将字符P[j]的BC项更新为j(单调递增)——画家算法/*DSA*/printBC ( bc );return bc;
}

最好情况—— O(n/m)


在当前情况下,p一共移动 n/m次就停止,所以最好情况是 O(n/m)

最坏情况—— O(n*m)

因为p从最末尾开始

可以发现BM算法也并非完美,故将BM_BC+KMP算法结合则会产生完美的算法

BM_GS算法

好后缀策略

概念

实例

构造GS表

  • 构造gs表的过程:MS【】——> ss【】——>gs【】
  • MS【】的含义↓



注意3 和 4的含义。

  • “I C E”与后缀最长匹配者
    ss【j】= MS【j】的长度= 3

  • “RICE”与后缀最长匹配者
    ss【j】= MS【j】的长度= 4

性能



注:n为文本串T的长度,m为模式串P的长度
蛮力算法BF:单次比对成功率越高其复杂度越高,最好O(n+m),最坏O(nm)
KMP算法:稳定一直保持线性时间复杂度O(n+m)
BM算法_BC:适合大字符集、单次比对失败率较高的情况,最好O(n/m),最坏O(n
m)
BM算法_BC+GS:充分补偿了BC的缺陷。故最好是O(n/m),最坏是O(n+m)

Karp-Rabin 算法:串即是数

凡物皆数

任何串都可以用 素数序列转化为自然数 N 表示出来。

串亦是数


若视作自然数比对,只需O(1)时间。

数位溢出

70bit???????不懂
70位的128进制才能表示十个位的自然数。咋算的?

散列压缩

基本构思:通过对比压缩后的指纹确定匹配位置,故只需要O(1)时间比对

散列冲突

有散列就有概率发生冲突,即有两个自然数%M 得到的值相等。
因此经过hash()筛选之后,还需要进行严格比对,方可确定是否匹配。

离Karp-Rabin算法只剩最后一步。。。

快速指纹计算


Karp-Rabin代码解析参考:https://blog.csdn.net/Shine__Wong/article/details/102095474
代码涉及将串转为数且要除余,来限定范围。

邓俊辉 数据结构与算法C++版 第十三章 串 ADT相关推荐

  1. 邓俊辉数据结构与算法学习笔记-第十一章

    文章目录 11.串 11.a ADT 11.b 串匹配 11.b1 串匹配 11.b2 蛮力匹配 11.c KMP算法 11.c1 KMP算法:从记忆力到预知力 11.c2 KMP算法查表 11.c3 ...

  2. 邓俊辉数据结构与算法学习笔记-第四章

    文章目录 栈和队列 a 栈的接口与实现 a1 栈 a2 实例 a3 实现 c c1-1 栈的典型应用 c1-2 进制转换算法 c1-3实现 c2-1括号匹配实例 c2-2 尝试 c2-3 构思 c2- ...

  3. 清华大学邓俊辉-数据结构MOOC笔记-树的概念及逻辑表示

    清华大学邓俊辉-数据结构MOOC笔记-树的概念及逻辑表示 有关概念: 与图论略有不同,数据结构中的树:1.需要为每一颗树指定一个特殊的顶点,作为"根"(root),对应rooted ...

  4. 邓俊辉数据结构学习心得系列——如何正确衡量一个算法的好坏

    数据结构这门课主要关注如何设计合理的数据结构和算法,来简化时间复杂度和空间复杂度. 想要科学的解决这样一个优化的问题,最核心的思想也是最基础的,就是要量化问题.这也是将数学运用在实际问题中的一个基石. ...

  5. 邓俊辉数据结构学习心得系列——数据结构中所研究的算法

    写在前面的话: 本文只是个人学习邓俊辉老师C++数据结构的整理,包含了很多个人的见解(从内容到材料的组织形式).所整理的内容不保证逻辑性和完整性,仅供参考. 算法的基本性质: 有正确的输入 有正确的输 ...

  6. 邓俊辉数据结构学习-3-栈

    栈的学习 栈的应用场合 逆序输出 输出次序与处理过程颠倒,递归深度和输出长度不易预知 不是很理解 实例:进制转换 大致思路:对于进制转换,我们一般使用的都是长除法,因此要保存每次得到的余数,但是最后算 ...

  7. 邓俊辉数据结构学习笔记3-二叉树

    二叉树及其表示 树 有根树 从图论的角度看,树等价于连通无环图.因此与一般的图相同,树也由一组项点〈vertex)以及联接与其间的若干条边〈edge) 组成.在计算机科学中,往往还会在此基础上,再指定 ...

  8. 邓俊辉数据结构学习笔记2

    列表 typedef int Rank; //秩 #define ListNodePosi(T) ListNode<T>* //列表节点位置template<typename T&g ...

  9. 邓俊辉数据结构学习-7-BST

    二叉搜索树(Binary-Search-Tree)--BST 要求:AVL树是BBST的一个种类,继承自BST,对于AVL树,不做太多掌握要求 四种旋转,旋转是BBST自平衡的基本,变换,主要掌握旋转 ...

最新文章

  1. C# Winform应用程序占用内存较大解决方法整理(转)
  2. 前端开发之JavaScript基础篇四
  3. ThinkPHP入门--后盾视频
  4. Vbox配置仅主机模式
  5. Android四大组件之BroadCast(续)
  6. 全国教学交流研讨会“教学为本”主题总结
  7. Flutter CupertinoSliverRefreshControl 苹果风格的刷新效果
  8. nginx动静分离配置_Nginx动静分离配置实例
  9. #分布式系统架构之# 事件驱动模式以及与之匹配的长时间处理过程讨论
  10. 团体程序设计天梯赛-练习集-L1-036. A乘以B
  11. python代码-在哪里编写python代码
  12. 基于AI分子力场模拟分子动力学
  13. 我在华为做外包的真实经历!
  14. DEL: 华为无线modem变无线路由器
  15. 反斜杆e,Linux下五彩斑斓的命令行输出
  16. 商品详情页商品属性选择,包含多规格
  17. 发布会签到系统_系统开发_创建项目及应用
  18. 信息与计算机,科学网—信息与计算机(1) - 姜咏江的博文
  19. Core Animation学习笔记—第二节Setting up Layer Objects
  20. 多重共线性是如何影响回归模型的

热门文章

  1. web集群之通过tomcat部署jpress应用
  2. 全球机场与航空公司准点率数据报告,为五一小长假做足准备
  3. 安徽阜阳计算机高中学校排名,安徽最强的五所高中,都是知名实力中学,考上就离名牌大学不远了!...
  4. scrapy爬取51job职位信息(针对2020.851job新的反爬虫机制)
  5. mysql leader/followers_Leader/Followers 模式
  6. yolo 深度学习_YoLo v1-v3深度学习网络-结构简介
  7. 论文笔记:3D-CVF(ECCV 2020)
  8. Win32创建菜单篇
  9. solidity msg.sender.transfer发送给谁
  10. Objective-C类别(catagory)