数据结构与算法——字符串匹配算法简介

371 阅读4分钟

这是我参与8月更文挑战的第16天,活动详情查看:8月更文挑战

单模式串匹配算法:也就是一个串跟一个串进行匹配

多模式串匹配算法:也就是在一个串中同时查找多个串

BF算法(Brute Force)

暴力匹配法(朴素匹配算法):简单易懂,性能不高

在A中查找B串,A是主串长度为m,B是模式串长度为n
概念:我们在主串中,检查起始位置分别是 0、1、2....n-m 且长度为 m 的 n-m+1 个子串,看有没有跟模式串匹配的。

这种算法的最坏情况时间复杂度是 O(n*m)。

RK算法(Rabin-Karp)

RK算法是BF算法的升级版

RK算法与BF算法基本类似,只是在比较n-m+1子串的时候,不是一个字符一个字符的匹配,而是通过hash算法将其转换成hash值进行比较

  1. 将主串A上的n-m+1个子串通过hash算法转换成hash值
  2. 比对模式串的hash值与子串的hash值
  3. 如果出现hash冲突,就比较原值是否匹配 最优时间复杂度是O(n),当全部hash冲突,那么时间复杂度就变成了O(n*m)

其效率依赖于hash算法,很多时候我们不针对类型来进行解决,所以hash算法就需要涵盖所有的数据类型.就会很麻烦

BM算法(Boyer-Moore)

性能非常高,但是实现起来会稍微麻烦些

核心理念

也就是说,模式串在匹配主串的子串时,一旦出现有一个字符匹配不上的情况,就可以往后多移动几位而不是只移动一位.

概念分析

坏字符规则

BF的子串匹配规则是从左往右,比如模式串是abc.主串是shabc,那么BF第一个比较的子串是sha,那么就是先比较第一个字符a与子串第一个字符s是否相等,不等就不匹配了,向后移动一个子串

BM的子串匹配规则是从右往左,也就是abcsha比较时,先比较c和a是否相等.再比较c和b是否相等,如果不等再比较c和a是否相等,如果再不等就可以直接将模式串向后移动三个方位格

  1. 从模式串的末尾往前倒着匹配,当发现某个字符没法匹配的时候,我们把这个没有匹配的字符叫作坏字符(主串中的字符)。
  2. 拿坏字符 c 在模式串中查找,发现模式串中并不存在这个字符,也就是说,字符 c 与模式串中的任何字符都不可能匹配。将模式串直接往后滑动三位,将模式串滑动到 c 后面的位置,再从模式串的末尾字符开始比较。
  3. 如果c在模式串中能找到,则将模式串后移直到和c对其,这样比对是否匹配整个模式串

不匹配的时候:坏字符对应的模式串中的字符下标记作 si。如果坏字符在模式串中存在,我们把这个坏字符在模式串中的下标记作 xi。如果不存在,我们把 xi 记作 -1。那模式串往后移动的位数就等于 si-xi。如果坏字符在模式串里多处出现,那我们在计算 xi 的时候,选择最靠后的那个,因为这样不会让模式串滑动过多,导致本来可能匹配的情况被滑动略过。

使用坏字符BM 算法在最好情况下的时间复杂度非常低,是 O(n/m)

好后缀规则

主串上有两个字符和模式串上匹配,但是第三个字符不匹配.将主串匹配的两个字符称为{u}

  1. 检查模式串上是否还有和{u}一样的字符串,如果有则移动使其对应

  2. 如果没有就直接将模式串移动到{u}下一个字符(还需要考察好后缀的后缀子串,是否存在跟模式串的前缀子串匹配的。)

案例

  1. 如何实现文本编辑器中的查找替换功能 BM算法实现

学习自极客时间的数据结构与算法之美