美文网首页
串的匹配模式

串的匹配模式

作者: hellomyshadow | 来源:发表于2020-06-19 15:49 被阅读0次

BF

暴力匹配,每次右移一位,时间复杂度O(MN)

RK

BF算法的改进,通过计算哈希值减少比较次数;
基本思想:

  • 如果Hash不同,则一定不匹配;
  • 如果Hash相同,再逐位比较。

时间复杂度O(MN),在实际应用中往往较快,期望时间为O(M+N),如论文查重。

用过哈希表的朋友们都知道,每一个字符串都可以通过某种哈希算法,转换成一个整型数,这个整型数就是HashCode

HashCode = hash(string)

sssddddeeer --> 39434
sssddddeaar --> 4358

很显然,相对于逐个比较两个字符串,仅比较两个字符串的HashCode要容易的多!

主串:abbcefgh
模式串:bce

第一步,生成模式串的HashCode

哈希算法

哈希算法有很多种,比如:

  • 按位相加
    这是最简单的方法,把a视为1b视为2c视为3。。。 然后把字符串的所有字符相加,所得结果就是HashCode
    hash(bce) = 2 + 3 + 5 = 10
    
    很容易想到,这个算法可能产生hash冲突,如bce、cbe、bec 的哈希值都是10
  • 转为26进制数
    小写字母一共有26个,可以把每个字符当成26进制数来计算,累加所得结果就是字符串的哈希值;
    hash(bce) = 2*(26^2) + 3*(26^1) + 5*(26^0) = 1435
    
    优点是大幅减少哈希冲突,缺点在于计算量较大,可能出现超出整型范围的情况,需要对结果取模。

匹配过程

使用 按位相加 进行匹配,在主串中生成与模式串等长的子串,并计算HashCode

匹配过程.png

第三次子串的哈希值与模式串相同,然后 逐位比较,判定每个字符都是相等的!

增量计算

如果每次都计算子串的哈希值,那么就可能把主串上的所有子串都以计算一遍,总的时间复杂度与BF算法相同--O(mn)!其实,从第二个子串开始,每个子串的哈希值都可以通过计算上一个哈希值的增量得到。

   第一个子串:hash(abb) = 1 + 2 + 2 = 5
   第二个子串:hash(bbc) = hash(abb) - a + c = 5 - 1 + 3 = 7
   ......

增量计算后的时间复杂度是O(n),相比BF算法,免去了许多无谓的字符比较。
缺点在于,哈希冲突,每次冲突都要逐字比较,如果冲突太多,就会退化成BF算法

相对而言,BF算法KMP算法 的思路更巧妙,性能也更加稳定。

BM

思想: 有模式串(子串)中不存在的字符,那么肯定不匹配,则向后多移动几位,提高效率;
规则:坏字符规则,好后缀规则 --- 相互独立,相辅相成;

字符串:HERE IS A SIMPLE EXAMPLE
搜索词(模式串):EXAMPLE

  1. 初次比较
首次匹配.png

从右向左开始比较,思路在于 只要尾部字符不匹配,前面的比较也就没有意义
图中,SE 不匹配,S 称之为坏字符,且搜索词中不包含 S,所以移动到坏字符S的下一个;

注:在搜索词中,坏字符对应的角标位置:6

  1. 二次比较
二次匹配.png

PE 不匹配,但搜索词中存在 P,则后移两位,让两个 P 对齐。

注:在搜索词中,坏字符对应的角标位置:6;坏字符在搜索词中的角标位置:4。

  1. 三次比较
三次匹配.png

坏字符规则:
后移位数 = 坏字符对应搜索词的角标位置 - 搜索词中的坏字符的角标位置
注意:如果搜索词中的坏字符有多个,则取最靠后的那个;如果搜索词中没有坏字符,则返回-1

由此规则可知:

  • 首次比较时的移动位数 = 6 - (-1) = 7
  • 二次比较时的移动位数 = 6 - 4 = 2

再来看看本次比较,后四位MPLE 全部匹配,MPLE、PLE、LE、E 都称为好后缀
IA 不匹配,所以 I坏字符。根据坏字符规则,理应移动 2 - (-1) = 3 位。

好后缀规则:
后移位数 = 好后缀的角标位置 - 好后缀上一次出现的角标位置

举两个栗子

  • ABCDAB 的后一个 AB 是好后缀,它的角标位置为 5(从 0 开始,取到最后一个 B),好后缀AB 在搜索词中上一次出现的位置是 1 (第一个 B 的位置),所以后移 5 - 1 = 4 位,前一个AB 移动到后一个AB的位置;
  • ABCDEFEF 是好后缀,则 EF 的位角标位置为 5,但前面没有 EF,所以返回 -1,对应的后移 5 - (-1) = 6 位,也就是移动到 F 的下一个位置。

回到三次匹配
所有的好后缀MPLE、PLE、LE、E 中,只有 E 在前面出现过,所以好后缀的后移位置 6 - 0 = 6 位。

坏字符规则移动 3 位,好后缀规则移动 6 位。
Boyer-Moore算法的基本思想:每次后移这两个规则之中的较大值

三次匹配.png
  1. 四次比较
四次匹配.png

按照坏字符规则移动 6 - 4 = 2 位。

  1. 五次比较
五次匹配.png

匹配成功!返回角标位置 17

代码实现

BM算法之所以能够在模式匹配中有更高的的效率,主要得益于它构造了两个跳转表:坏后缀表好后缀表

匹配具有类似特点的模式串和主串时,BM算法非常高效;比如主串aaabaaabaaabaaab,模式串aaaa,每次比对都会后移 4 位。但是,单纯利用坏字符是不够的,因为移动位数可能是负数,比如主串aaaaaaaaaaaaaaaa,模式串baaa,不但不会前进,还可能倒退!所以BM算法还需要好后缀规则
另外,好后缀规则可以完全独立于坏字符规则来使用,虽然效率可能会降低一些,但在对内存要求苛刻的环境中比较实用。

时间复杂度

BM算法 的时间复杂度非常复杂,最坏时间复杂度O(mn),最优时间复杂度O(n/m)
在实际应用中,BM算法 经常能达到平均效率,有些场景下的效率甚至会高于KMP算法

KMP

KMP算法BM算法十分相似,它们的目标都是让模式串在每一轮多移动几位,减少无谓的字符比较。
为了实现这一点,KMP算法 把专注点放在了 已匹配的前缀,关键在于 next数组 -- 部分匹配表 的推导。

相关文章

  • 多模式串匹配 - AC 自动机

    多模式串匹配概念 多模式串匹配,即多个模式串在一个主串中进行匹配。 虽然单模式串也能完成多模式串的匹配,但每个模式...

  • 模式匹配中Brute-Force与KMP算法关键提取

    模式匹配是串结构的一种操作方法,用于串的匹配。待匹配串称为主串(也叫目标串),执行串称为子串(也叫模式串)。模式匹...

  • 字符串模式匹配KMP

    主串S: [0...n-1]模式串T: [0...m-1]模式匹配:返回模式串在主串中的位置 蛮力法 简单模式匹配...

  • 模式匹配

    模式匹配之字符串 模式匹配之匹配类型 模式匹配之匹配数组、元组、集合 模式匹配之样例类 模式匹配之偏函数

  • BF算法 KMP算法(普通、快速模式匹配算法)及C语言

    判断两个串之间是否存在主串与子串的关系,这个过程称为串的模式匹配。 在串的模式匹配过程,子串 T 通常被叫做“模式...

  • 数据结构学习第三弹 串(2) 匹配模式

    串的模式匹配 串的模式匹配也可以说子串的定位,是一种重要的串运算。所谓模式匹配就是给定两个串s1和s2,在主串s1...

  • 数据结构与算法学习 (08)字符串匹配--BF算法/RK算法

    BF算法也就是串的模式匹配算法,在主串中查找与模式T(副串)相匹配的子串,如果匹配成功,找到该子串在主串出现的第一...

  • AC自动机

    字符串匹配算法 单模式串匹配算法 是在一个模式串和一个主串之间进行匹配,也就是说,在一个主串中查找一个模式串。 多...

  • 数据结构与算法串的模式匹配

    1.简单的模式匹配算法子串的定位通常称为串的模式匹配,它求的是子串的(常称模式串)在主串中的位置 实现思想:将主串...

  • Python算法-字符串(String)

    字符串匹配问题字符串匹配(String Matching):又称为模式匹配(Pattern Matching)。可...

网友评论

      本文标题:串的匹配模式

      本文链接:https://www.haomeiwen.com/subject/vixvxktx.html