串的模式匹配算法

在代码中的模式匹配往往都是写好的接口, 基本上只需要用一句代码可以实现.


匹配字符串中的子字符是如何实现的呢? 假设我们以 S 代表目标串,即父串(例如 aeaaefababdc), 以 T 代表模式串即子串(例如 abd), i 代表 S 中字符位置, j 代表 T 中字符位置, 即下标. 我们要做的是匹配是否 abcdefabdc 中存在 aeaad.

  • 最常用的是使用朴素匹配算法
    朴素匹配算法的原理是使用模式串 T 和目标串 S 的每一个字符都进行比较, 是一种有回溯的算法. 算法的时间复杂度无 O(m+n), m,n 分别代表目标串和模式串的长度.
    1 首先我们令 i = 0, j = 0.
    2 把 S 的第一个字符 S[0] 和 T 的第一个字符 T[0] 进行比较. (例子中 S[0] = T[0] = a)
    3 如果相同则 i, j 分别+1 . (例子中 继续比较 S[1] 和 T[1], S[1] = T[1] = b)
    4 直到出现不相同S[i] != T[j]. (例子中 S[4] = e != T[4] = d)
    5 重新比较 S 的第二个字符 S[1] 和 T 的第一个字符 T[0] , 重复执行步骤3,4直到匹配成功或所有都匹配不成功.
  • KMP 匹配算法
    在许多时候, 朴素算法的回溯增加了大量的运算时间, 特别是当模式串和主串有许多部分匹配的情况下. 因此 D. E. Kunth 与 J. H. Morris 和 V. R. Pratt对算法做出了改进, 使得算法不需要回溯, 并且可以在 O(m+n)的时间复杂度上完成串的匹配, 称为 KMP 匹配算法.
    KMP 匹配算法相对朴素匹配算法的改进之处在于, KMP 匹配算法会对匹配串本身进行一次匹配, 目的是为了当匹配串和目标串"失配"时, 确定模式串中和需重新和主串中的"失配"那一位字符进行比较的位置. 即模式串的 next[j] 函数.
    1 首先我们令 i = 0, j = 0.
    2 把 S 的第一个字符 S[0] 和 T 的第一个字符 T[0] 进行比较. (例子中 S[0] = T[0] = a)
    3 如果相同则 i, j 分别+1, 继续比较 S[1] 和 T[1]. (例子中 S[1] = T[1] = b)
    4 直到出现不相同S[i] != T[j]. (例子中 S[2] = c != T[2] = d)
    5 模式串 T 退回到 next[j] 指示位置与 S 失配位置 S[i] 进行比较. (例子中next[j] = 2, 对比S[4] = e 和 T[2] = a, 从而跳过了 S[1] - S[3] 以及 T[0] 和 T[1] 的比较.)
    6 重复3,4,5直到匹配成功或所有都匹配不成功.
  • 虽然 KMP 匹配算法无需回溯, 但是仅有当模式串和主串有许多部分匹配的情况下在时间复杂度上有明显的优势. 又因为朴素匹配模式算法在一般情况下执行时间近似 O(m+n), 因此朴素匹配模式算法仍在被大量采用.
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 引言 字符串匹配一直是计算机科学领域研究和应用的热门领域,算法的改进研究一直是一个十分困难的课题。作为字符串匹配中...
    潮汐行者阅读 1,818评论 2 6
  • 首先总结以下Java和C、C++中的一般控制台输入方式,方便以后的编程题: java键盘输入 java读文件(会自...
    androidjp阅读 2,384评论 0 16
  • 数据结构 第8讲 KMP算法 讲这个算法之前,我们首先了解几个概念: 串:又称字符串,是由零个或多个字符组成的有限...
    rainchxy阅读 1,464评论 0 3
  • 本文参与#漫步青春#征文活动,作者:沈须晴。本文承诺。文章内容为原创,且未在其他平台发布过。 我说青春是远方 背上...
    23333lin阅读 446评论 0 0
  • 孤独是一种兽性, 很低等的动物,多半是合群的。比如海洋里庞大的虾群,丛林中的白蚁,都是数目庞大的聚合体。随着物种渐...
    eleven葱阅读 396评论 2 1

友情链接更多精彩内容