字符串匹配算法总结
在一个主串中匹配模式串
BF算法
最简单的使用strcmp
逐个匹配的算法, 通常情况下我们使用这个就可以了; 假设主串长度为m
, 模式串为长度为n
, 时间复杂度为O(m * k * n)
(我们需要匹配m
次, 每次的耗时和n
有关)
RK算法
和BF算法相同的逐个匹配, 优点是使用HASH
的方式进行逐个比较; 且如笔者写的示例, 我们可以使用的HASH
算法中HASH(N)
是和HASH(N-1)
有关的.时间复杂度为O(m * s)
, 这个s
在通常情况下是k*n
应当要小的。
不过考虑到HASH
冲突的情况, 效率未必会高很多.
BF算法
使用坏字符
和好后缀
规则, 一次尽可能多的移动位数; 时间复杂的为O(M * N)
, 这里的M
应当是小于主串的长度的.
需要注意的是, 如果模式串太短的话, 意义不大; 而且需要额外的空间存储一些辅助的结构体, 同时建立辅助结构体是需要是假的呢.
坏字符规则: 如果在匹配中遇到了第一个坏字符(不匹配的字符), 那么向后移动时: 需要在模式串中找到一个和该坏字符相同的字符移动到对应位置, 否则必不会成功的。
好后缀规则: 如果在从后往前匹配时, 遇到第一个坏字符之前已经匹配了一段后缀子串; 那么我们进行移动时, 就必须考虑和这个后缀子串的匹配情况.
KMP算法
这里和BF算法相同的是利用好前缀
规则, 尽可能移动多的位数; 假设从前往后匹配时: 我们已经匹配了一部分的前缀子串, 那么当我们往后移动时, 必须要找到该前缀子串的后缀子串与该前缀子串的前缀子串的匹配情况.
ps: 这里仅仅是做一个简单的说明总结, 详细的可以看我的BLOG, 如果仅仅看这里应当是很难看懂这些规则的!!!
一个字符串匹配多个模式串
Trie树
Trie树注重的是模式串的前缀匹配问题, 比如输入一个单词的前半部分我们能够知道到和这前半部分匹配的单词(主串可能等于或者短于模式串).
简单实现, 如果我们考虑更多的字符/汉字等等, 对空间的消耗是非常大的(实际工作中使用的话, 可能要优化子节点的保存方式)。
AC自动机
AC自动机, 负责的问题是一个字符串匹配多个模式串的问题, 比如在一个长字符串中匹配屏蔽的单词.简单实现.
总结
- 利用
HASH
的方式可以极大的减少, 比较/寻址的消耗 - 将一些需要的数据提前算好, 避免在循环中不断计算
- 根据使用情况决定采取哪种算法, 需要考虑 时间复杂度/空间复杂度, 除此之外 代码复杂度也是需要考虑的问题.