Skip to content
难度基础(★)
建议时长45分钟

13.1.4 串

串是由零个或多个字符组成的有限序列。考试中串的概念题不难,真正有区分度的是模式匹配,尤其是普通匹配与 KMP 改进匹配的差别。

基本概念

概念含义
字符组成的有限序列
空串长度为 0 的串
子串串中任意连续字符组成的序列
主串被匹配的大串
模式串要在主串中查找的小串
模式匹配判断模式串是否出现在主串中,并找到位置

普通模式匹配 BF

BF 算法用两个下标比较:i 指向主串,j 指向模式串。

mermaid
flowchart TD
  A["比较 s[i] 与 t[j]"] --> B{"相等?"}
  B -->|是| C["i++,j++"]
  C --> D{"j 到达模式串末尾?"}
  D -->|是| E["匹配成功"]
  D -->|否| A
  B -->|否| F["主串回到本轮起点下一位,模式串 j 回到起点"]
  F --> A

普通匹配的问题在于:一旦中途失败,模式串下标回到起点,主串也要退回到本轮起点的下一位。模式串较长、重复前缀多时,会产生大量重复比较。

KMP 的改进思想

KMP 的核心不是“比较更快”,而是“失败后不让模式串盲目退回开头”。它预先为模式串计算 next 数组,记录每个位置失败时应该回退到哪里。

算法失败时怎么退
BF模式串回到起点,主串回到本轮起点下一位
KMP主串不回退,模式串回到 next[j] 指定的位置

课程强调:软考不一定要求完整证明 KMP,但要知道 next 数组的作用和失败回退的特殊点。

next 数组怎么理解

next[j] 记录的是模式串在第 j 个位置失配时,j 应回退到的位置。它只依赖模式串本身,长度与模式串长度一致。

一种常见定义是:

next[1]=0

j>1 时,寻找满足“前缀等于后缀”的最大 k。如果不存在可用的 k,则取某个约定初值,例如 1。不同教材的下标起点和 next 定义可能略有不同,考试要以题目给出的定义为准。

为什么不同资料的 next 值会不一样

KMP 的版本很多,差异主要来自:

差异来源表现
下标从 0 还是从 1 开始next[0]next[1] 初值不同
失配后 j 指向哪里有的记录最长相等前后缀长度,有的记录下一次比较位置
是否使用改进 nextval对重复字符会进一步跳过无效比较

因此复习时不要死背某一组数值,要看题目给的递推式和下标约定。

BF 与 KMP 的技术迭代

算法优点缺点为什么出现后继改进
BF思路直观,容易实现失配后回退多,最坏复杂度高长文本和重复模式下效率差
KMP主串不回退,利用模式串自身规律next 数组理解和计算较难用预处理换匹配效率
nextval 改进避免部分重复字符导致的无效比较规则更细,考试不一定要求进一步减少回退比较

本节例题

单选
KMP 算法中 `next` 数组的主要作用是:

自查清单

  1. 能否区分主串、模式串和子串?
  2. 能否画出 BF 算法失配后的回退过程?
  3. 能否说明 KMP 为什么主串不需要回退?
  4. 看到 next 题时,能否先确认下标从 0 还是从 1 开始?