《考研408数据结构》第四章(串和串的算法)复习笔记

一、串的概念

1、串的定义

太简单了就是代码里的字符串,跨专业的自己看下面图吧

2、串的操作

3、串的顺序结构

有这么四种方案,没什么好说的,哪怕是跨考的学一节应该也看得懂

4、串的链式存储结构

依旧没什么好说的,看一眼就行

二、开始有用的部分

专业术语**【模式串**】解释:

而这种在【主串】中找到某个和【模式串】匹配的【子串】,并返回该【子串第1个字符在主串的位置】的运算就叫------------------【模式匹配】

1、朴素模式匹配算法

没什么好说的,写过代码的应该看得懂下面图,就是【主串】取【和模式串一样长的子串】一一对比,一旦不同,【主串的子串】整体往后挪一位,又从头开始一一对比

可以记一下,主串长度n、模式串长度m,看上面图主串里的【子串的头】最多移动到【n-m+1位】,也就是最多对比【n-m+1】个子串

然后简单记一下代码逻辑:

  • 1、遍历【主串的指针i】和【遍历模式串的指针j】初始位置都是0
  • 2、若某一位匹配失败,因为i和j都是对应子串相对一样 的位置,那么:
    • 【i】就应该等于【i-j+2】,因为:
      • 【i-j】就是回到**主串的【当前子串】**的开头前一位
      • 【i-j+1】就是回到**主串的【当前子串】**的开头第一位
      • 【i-j+2】就是回到主串的【当前子串】开头前二位,那么就可以以他为【下一个子串的开头第一个元素
    • 而【j】直接等于1,回到自己模式串的开头第一位即可
  • 3、而如果找到了主串中【匹配模式串的子串】
    • 那就很简单,返回【这个子串第一个字符的位置】

朴素模式匹配算法【时间复杂度】

  • 主串长度n、模式串长度m,【时间复杂度:O(n*m)】
    • 主串需要最多对比【n-m+1】个子串,就是近似n*m

【例题】

2、KMP算法

这玩意太几儿抽象了,必须先从人类视角解决概念,然后再讲具体实际程序运行是怎样的

1)纯抽象概念解释

为了弥补朴素模式匹配算法太慢,KMP算法实现了线性的时间复杂度

【首先先不考虑计算机,仅从人的视角出发】

  • 一个【模式串】跟【主串的子串】对比时,既然双方指针都能遍历到后面,指针前的元素肯定是对应一样匹配的
    • 就说明当出现不匹配时,我们没必要再把让它两再次回到头,从头往后对比
    • 而是应该从【不匹配的那位字符】往前找到一个【前后缀】,在【模式串】里的【也有一样的前后缀】,既然都一样了,那就二者都跳过这个【相同前后缀】,从它的后一位开始对比
      • 【主串的子串】的指针已经是在【相同前后缀】的后一位了,指针可以不用动
      • 【模式串】的指针则需要跳到这个【相同前后缀】的后一位
  • 那么如何实现让模式串找到这个**【相同前后缀】的后一位**?
    • ① 多加一个【next数组】用来统计模式串【每一位出现不匹配】时,对应的【指针应该跳到哪?】

    • ② 而【next数组】的本质就是:记录模式串里,每一位【作为后缀、最长、有相同的前后缀的长度】

      大概流程就是下图这样:

KMP模式匹配算法【时间复杂度】:

  • 主串长度n、模式串长度m,【时间复杂度:O(n+m)】
  • 主串只用一次性遍历一次,记住了是线性时间复杂度!!

2)具体程序怎么实现这逻辑?

现在,计算机视角,别特么管前面的什么逻辑了,计算机跟人不一样,我们直接暴力计算:

  • 1、首先,在得出【next数组】时,我们还需要设置一个【PM数组】,别问为什么,我也不知道,我只知道老子考试做题就按这个步骤来
  • 2、【PM数组】对应统计【模式串的每一位】前面的【最长相同前后缀】的【长度】
    • 听不懂没关系,完全没关系,看流程照做就行
    • 【第一步】:模式串第一位一定是0,什么都别管直接写0就行了
    • 【第二步】:第1位和第2位对比,一样的话,第2位的值是0;不一样则第2位是0
    • 【第三步】:接下来【指针 j:指向第1位】、【指针 i:指向第3位】,它两开始正常同步往后遍历
      • 【如果 PM[i] == PM[j]】:那么i连起来的字符串和j连起来的字符串一直一样,那就【PM[i] = PM[i-1]+1,统计相同最长前后缀长度】就行,也就是一直累加
      • 【如果 PM[i] != PM[j]】:那么**【i 不要动!!】**,【指针 j 一步步往回遍历】
        • 直到【指针 j 】找到【PM[i] == PM[j]】的字符,那么这个字符对应的PM是什么值,PM[i]就等于它+1,即【PM[i] = PM[j] + 1】
  • 3、得出了【PM数组】后,再变两步就可以得到【next数组】了:
    • 首先:把PM整体右移1位,第一位写-1
    • 最后:整体每一位都+1,得到next数组(最后一位记得舍去就行了)
    • 别问为什么,我有点懒得剖析它的原理了。。。老子只是考试狗而已
      • 另外我这是为了写清楚给大家看,考试做题大家画一个数列在上面涂涂改改就行了,别像我这样写这么清晰的步骤
      • 【另外】上面是字符串以【1为开头】的情况,如果是以【0为开头】的话,那PM转化成【next数组】时只需要【右移 + 开头补上-1】到这一步就够了!!!

3、KMP优化算法

那么还有一种【next数组】Pro升级星耀版!!!------------【nextval数组】!!!

【nextval数组】 也叫**【修正后的next数组】**)

我们需要知道原理吗?不需要!!写代码用不上!考试狗应试教育更用不上!!!

所以直接讲步骤怎么求得【nextval数组】:

  • 【第一步】:把刚刚求出的【next数组】抄在模式串下
    • 然后给模式串【列序号(从1开始)】
    • 然后在【next数组下】把**【每个值】对应的是【模式串的哪个序号的字符】** 列在下面,得出一个**【新的字符串(第1位不用写,空着)】**
  • 【第二步】:然后把【新字符串】个【模式串对比】
    • 从【新字符串】第2位开始,找出所有**【和模式串不一样的字符】!!!再三强调!!!是【不一样的】**!!!!
      • 直接把不一样的这些字符对应的**【next数组的值】照抄到下面,作为【nextval】当前位的值**
    • 然后**【nextval数组】的【第1位】**依旧跟【next数组】一样,默认是0
    • 然后【新字符串】里剩下【和模式串一样的字符位】,我们根据上面【 next[i] 】找到【 nextval[ next[i] ] 】,就是【next[i]的值】
      • 即**【 next[i] = nextval[ next[i] ] 】**!!!!!!!!!
      • 而且强调,【nextval数组】也是从1开始

【例题】

未完待续。。。。。。。

相关推荐
2401_841495646 小时前
【数值分析】插值法实验
python·数学·算法·可视化·数值分析·数学原理·插值法
Tony_yitao6 小时前
符号运算(华为OD)
java·算法·华为od
冬夜戏雪6 小时前
记录下C盘清理步骤(有效)
经验分享·笔记
我登哥MVP6 小时前
Apache Tomcat 详解
java·笔记·tomcat
feifeigo1236 小时前
MATLAB的无线传感器网络(WSN)算法仿真
网络·算法·matlab
胖咕噜的稞达鸭7 小时前
缝合怪deque如何综合list和vector实现及仿函数模板如何优化priority_queue实现
数据结构·c++·算法·链表·list
tt5555555555557 小时前
C++ 经典数组算法题解析与实现教程
开发语言·c++·算法
美团技术团队7 小时前
可验证过程奖励在提升大模型推理效率中的探索与实践
人工智能·算法