全网最幼稚园级别的字符串匹配算法科普,手把手带你辨别字符串匹配的花样套路。
字符串的模式匹配是NLP领域的基础任务,可以帮助我们在大量的文本内容中快速找到需要的文本信息,比如在文章中搜索关键词的位置和数量。
字符串模式匹配问题按照具体任务类型可以分为单模式匹配和多模式匹配。单模式匹配是指匹配模板为单个字符串,即从待匹配字符串
本文主要介绍单模式匹配的常见算法:
- 朴素查找算法 Naïve String Search Algorithm
- Sunday算法 Sunday Algorithm
- KMP算法 Knuth–Morris–Pratt Algorithm
- BM算法 Boyer–Moore Algorithm
1 朴素查找算法
朴素查找算法又被称为暴力算法(Brutal Force),是待匹配字符串
如下图所示,蓝色表示匹配,红色表示失配。
朴素算法的思路简单,完全没有考察pattern本身的特点,没有考察匹配部分和未匹配部分的特点,进行了很多完全没有必要的比对。
下面要介绍的算法,会通过研究模板和待匹配字符串的特点,跳过一些不必要的比较,让
2 Sunday算法
Sunday算法是Daniel M.Sunday于1990年提出的字符串模式匹配算法,它比后面要介绍的KMP算法和BM算法都要晚提出。不过其逻辑和处理方式比后二者要更简单清晰,故提前介绍。
Sunday算法会提前记录
在每一次的比较中,一旦出现失配,算法会去看
看下面的例子:
新的位置仍然失配,
可以看到,巧妙地利用字符串的特点可以有效减少匹配的次数,提高匹配效率。
3 KMP算法
Knuth–Morris–Pratt Algorithm是以3个发明者的名字命名的字符串匹配算法,类似的,它也通过右移
该算法需要提前计算
对于字符串 :"abcab",其PMT表格为:
可以看到表格中PMT[3]=1,即前缀子串"abca"的PMT值为1,具体的计算过程如下:
查看
- 所有前缀:{"a", "ab", "abc"}
- 所有后缀:{"a", "ca", "bca"}
前缀和后缀的最大重叠的字符串为"a",故其PMT值为1。
下面我们来看,怎么在具体的例子中应用PMT:
图中,该匹配段在最后一个字符失配,已经匹配成功的子串
右移3位之后,匹配部分
可以看到,计算PMT的主要目的,是通过研究模板
4 BM算法
Boyer-Moore算法是于1977年由德克萨斯大学的 Robert S. Boyer 教授和 J Strother Moore 教授提出。
4.1 坏字符规则 Bad-Character Heuristics
对
上图中
上图新的位置失配字符
可以看到,仅仅使用坏字符规则,
4.2 好后缀规则 Good-Suffix Heuristics
对成功匹配的后缀子串 ,考查:
- 如果
- 如果
在刚才的匹配中,坏字符规则后的中间步结果为:
当前匹配成功的子串
为了解释好后缀规则的第2种情况,这里引入一个新的例子来介绍:
当前匹配成功的子串
以上即对好后缀规则的两种情况的介绍。
在应用中,坏字符和好后缀规则会分别给出右移距离,选择较大的那个右移距离,不允许出现走回头路的情况发生。
可以看到,BM算法中,坏字符规则类似于Sunday算法(实际上是Sunday算法在BM的基础上的改进),好后缀规则类似于KMP算法。这些算法的原理和规则实际上都是利用字符串自身的特点和匹配时的特征,使可以跳过确定无法匹配成功的位置,从而加快搜索的速度。
参考文献
- Sunday 字符串匹配算法(C++实现) http://www.cnblogs.com/lyc94620/p/11420092.html
- 字符串匹配的Boyer-Moore算法 https://www.ruanyifeng.com/blog/2013/05/boyer-moore_string_search_algorithm.html
- 字符串匹配的KMP算法 https://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html
- 算法之「字符串匹配算法」 https://juejin.im/post/5ccef225e51d456e4b3c6f31
- 浅谈字符串匹配 https://blog.brickgao.com/2015/08/08/string-searching-algorithm/
更多优质文章首发于公众号「朴素人工智能」,订阅它!
http://weixin.qq.com/r/SkistK3Eu-DErenX9x1Y (二维码自动识别)