【数据结构】串的模式匹配(朴素匹配+KMP+nextval)

数据结构|串的模式匹配(朴素匹配+KMP+nextval)

说明:本文下标从 1 开始

文章目录

1.基本概念

模式匹配是指在主串中查找与模式串(待搜索的字符串)完全相同的子串,并返回其首次出现的位置

子串与模式串的区别:

  • 子串:是主串的一部分,在主串中一定存在
  • 模式串:待搜索的字符串,在主串中不一定存在

2.朴素模式匹配算法:

朴素模式匹配算法的时间复杂度O(mn)

核心思想

逐个对比主串和模式串的字符,如果字符匹配不成功,模式串回溯到第一个位置,主串回溯到本轮起始位置的下一个位置重新匹配,直到找到主串中与模式串完全相同的子串,返回子串起始位置

字符匹配失败时

  • i = i - (j - 1) + 1 = i - j + 2
  • j = 1

匹配成功

返回模式串在主串中首次出现的位置:return i - T.length;

3.KMP算法

KMP算法是对朴素模式匹配算法的优化

核心思想

匹配失败时i不回退,仅通过预处理得到的next数组调整 j 的位置,避免了重复字符的比较,从而将时间复杂度从O(mn)优化为O(m + n)

时间复杂度

  • 预处理next数组 O(m)
  • 匹配 O(n)
  • 总时间复杂度 O(m + n)

4.next数组的计算

nextj的含义

当模式串的第j个字符失配时,下一轮应从模式串的nextj位置开始比较

规则

  • next1 = 0,next2 = 1
  • 从模式串的第三个字符开始,next数组的值是模式串中当前字符之前的串的最长公共前后缀的长度+1

例1:T = ababaa

下标 1 2 3 4 5 6
next 0 1 1 2 3 4

next1 = 0, next2 = 1

从模式串的第3个字符 a 开始:

  • 第3个字符 a 前面是 "ab",没有公共前后缀,所以next3 = 0 + 1 = 1
  • 第4个字符 b 前面是 "aba",最长公共前后缀是 "a",长度是1,所以next4 = 1 + 1 = 2
  • 第5个字符 a 前面是 "abab",最长公共前后缀是 "ab",长度是2,所以next5 = 2 + 1 = 3
  • 第6个字符 a 前面是 "ababa",最长公共前后缀是 "aba",长度是3,所以next6 = 3 + 1 = 4

例2:T = aaaab

下标 1 2 3 4 5
next 0 1 2 3 4

next1 = 0, next2 = 1

从模式串的第3个字符 a 开始

  • 第3个字符 a 前面是 "aa",最长公共前后缀是"a",所以next3 = 1 + 1 = 2
  • 第4个字符 a 前面是 "aaa",最长公共前后缀是 "aa",长度是2,所以next4 = 2 + 1 = 3
  • 第5个字符 b 前面是 "aaaa",最长公共前后缀是 "aaa",长度是3,所以next5 = 3 + 1 = 4
    注意 字符串的公共前后缀不包含字符串本身,如字符串"aaa"的公共前后缀是"aa"而不是"aaa"

5.KMP算法的进一步优化

在使用KMP算法进行模式匹配时,如果模式串j对应的字符和主串i对应字符不相等(失配)则将j移动至next[j]继续匹配,但j移动后指向的字符可能和移动前指向的字符相同,此时出现了重复的比较并且一定会失配,所以可以使用nextval数组优化这种重复比较的情况

nextval数组的计算

  • nextval1 = 0
  • 从第 2 个字符开始
    • 当模式串中j对应的字符和nextj对应的字符相等 时,nextvalj的值等于nextj的nextval值,即 nextval[j] = nextval[next[j]]
    • 当模式串中 j 对应的字符和nextj对应的字符不相等 时,nextvalj的值等于nextj的值,即 nextval[j] = next[j]

例1:T = ababaa

下标 1 2 3 4 5 6
next 0 1 1 2 3 4
nextval 0 1 0 1 0 4

nextval1 = 0

从模式串的第2个字符 a 开始:

  • next2 = 1,T.ch1 = a,T.ch2 = b,字符不相等 -> nextval2 = next2 = 1
  • next3 = 1,T.ch1 = a,T.ch3 = a,字符相等 -> nextval3 = nextvalnext\[3] = 0
  • next4 = 2,T.ch2 = b,T.ch4 = b,字符相等 -> nextval4 = nextvalnext\[4] = 1
  • next5 = 3,T.ch3 = a,T.ch5 = a,字符相等 -> nextval5 = nextvalnext\[5] = 0
  • next6 = 4,T.ch4 = b,T.ch6 = a,字符不相等 -> nextval6 = next6 = 4

例2:T = aaaab

下标 1 2 3 4 5
next 0 1 2 3 4
nextval 0 0 0 0 4

nextval1 = 0

从模式串的第2个字符 a 开始:

  • next2 = 1,T.ch1 = a,T.ch2 = a,字符相等 -> nextval2 = nextvalnext\[2] = 0
  • next3 = 1,T.ch1 = a,T.ch3 = a,字符相等 -> nextval3 = nextvalnext\[3] = 0
  • next4 = 2,T.ch2 = a,T.ch4 = a,字符相等 -> nextval4 = nextvalnext\[4] = 0
  • next5 = 3,T.ch3 = a,T.ch5 = b,字符不相等 -> nextval5 = next5 = 4
相关推荐
船厂电气自动化ai大模型几秒前
AI大模型与数学·第57课 傅里叶全套工具链综合实战:串联级数/连续变换/DFT/FFT,图像、音频、扩散模型完整例题
数据结构·人工智能·深度学习·算法·机器学习
wuyk5556 分钟前
从零吃透Modbus通信|第3章:STM32 Modbus RTU主机
服务器·开发语言·网络·数据结构·stm32·单片机·嵌入式硬件
人工智能培训1 小时前
人工智能数据安全下的个人信息保护实践方案
大数据·人工智能·算法·生活
Brilliantwxx1 小时前
【算法从零到千】【59-65】链表专题
数据结构·链表
元启数宇2 小时前
幕墙AI设计算法逻辑:元启数宇如何智能分格
人工智能·算法
宵时待雨2 小时前
优选算法专题16:多源BFS
算法·宽度优先
重生之后端学习2 小时前
53. 最大子数组和[中等]✅
java·数据结构·算法·leetcode·职场和发展
INGNIGHT2 小时前
1908 · 布尔表达式求值(stack单调栈&dfs)
开发语言·c++·算法
lucas_AI2 小时前
把表格压成 64 个 token,长文档问答反而更准了:先找表,再看数
人工智能·深度学习·算法
Zzz 小生3 小时前
Lazy Theta*:把昂贵的视线检测留到“真正需要”时再做
人工智能·算法·贪心算法·推荐算法