![.NET源码学习 [算法2-数组与字符串的查找与匹配]](http://shimg.jingyanzongjie.com/230724/1516291029-75.png)
文章插图
—— —— —— —— —— —— —— —— —— —— —— —— —— ——
- 最后来看一下 , 如何根据这两个数组计算出滑动的位数
![.NET源码学习 [算法2-数组与字符串的查找与匹配]](http://shimg.jingyanzongjie.com/230724/15162a640-76.png)
文章插图
如果 suffix[ k ] = -1 , 说明模式串中不存在与好后缀匹配的子串 。此时 , 使用好后缀的另一条规则:查找好后缀中 , 所有后缀子串中 , 能与模式串前缀子串匹配的 , 最长的那一个后缀子串 。好后缀 pat[ j + 1, m – 1 ]的后缀子串 pat[ r, m – 1]( j + 2 <= r <= m – 1 )记作 { v } , 其长度 k = m – r 。若 prefix[ k ] = true , 表示长度为 k 的后缀子串 , 存在可匹配的前缀子串 { v* } , 则将模式串移动 r 位 。如图:
![.NET源码学习 [算法2-数组与字符串的查找与匹配]](http://shimg.jingyanzongjie.com/230724/15162a031-77.png)
文章插图
如果在模式串中没有找到与好后缀可以匹配的前缀子串 , 也没有找到好后缀中可匹配模式串中前缀子串的 , 后缀子串 , 则将整个模式串后移 m 位 。如图:
![.NET源码学习 [算法2-数组与字符串的查找与匹配]](http://shimg.jingyanzongjie.com/230724/1516292Q7-78.png)
文章插图
—— —— —— —— —— —— —— —— —— —— —— —— —— ——
代码实现:【注:考虑到时间成本与篇幅问题 , 在此不做BM算法的同意主串多次匹配问题 , 如有兴趣欢迎自行研究 , 本人也可能会在今后放出可对同一主串多次匹配的代码】
![.NET源码学习 [算法2-数组与字符串的查找与匹配]](http://shimg.jingyanzongjie.com/230724/15162945M-79.png)
文章插图
复杂度分析:
- 时间复杂度为O( n ) 若模式串中包含大量重复字符 , 则计算两个数组的时间将会达到 O( m2 ) , 但一般不会出现这样的极端情况 。
- 空间复杂度为O( m )
![.NET源码学习 [算法2-数组与字符串的查找与匹配]](http://shimg.jingyanzongjie.com/230724/15162913R-80.png)
文章插图
这就是一种极端情况 , 存在大量重复字符 , 导致其效率严重下降 。
总结—— —— —— —— —— —— —— —— —— —— —— —— —— ——
—— —— —— —— —— —— —— —— —— —— —— —— —— ——
至此 , 四种匹配方法全部介绍完毕 , 总结一下:
1. BF纯暴力算法 , 一位以为比较 , 遇到不匹配的从模式串开头在此一位一位比较 。时间复杂度较高 , 但简洁明了思路清晰 , 因此在实际应用中最为常用 。
2. RK算法 , 基于BF的比较字符的思想 , 转化为比较子串的哈希值 。数值间的比较确实比字符比较快 , 而且利用滑窗的思想将计算哈希的时间复杂度将为 O( n ) , 但容易存在哈希冲突的问题 , 冲突后需要对 两部分子串进行完整比较 。计算哈希方式越简单、字符串越长 , 冲突的概率越高 , 复杂度也会接近 O( n2 ) 。
3. KMP算法 , 利用某一特殊的规律 , 减少在不匹配时向后退回的位数 , 以达到降低时间复杂度的目的 。
4. BM算法 , 结合贪心思想 , 进一步对KMP进行优化 。但这两种方法过于复杂 , 掌握很不容易 。
经验总结扩展阅读
- 【前端必会】不知道webpack插件? webpack插件源码分析BannerPlugin
- 如何开展学习十八大,提高了教育的质量
- 十岁小孩学习不太好跟家长又不会怎么教他呢
- 20220929-ArrayList扩容机制源码分析
- 高效上课学习方法
- 怎么做一个学习的人
- Optional源码解析与实践
- Go 源码解读|如何用好 errors 库的 errors.Is 与 errors.As() 方法
- .Net下的分布式唯一ID
- .NET 反向代理 YARP 代理 GRPC
