【重学数据结构与算法(JS)】字符串匹配算法(一)——BF算法

前言

一切都要从 LeetCode 的第 28 题 实现 strStr()开始提及,当本身脑子里的第一种暴力查找法写出来并 AC 以后,仍是以为不知足,决定把能找到的解法都理解了,因而便有了这个系列。算法

字符串匹配的总体思路

当我理解完四种经典的匹配算法以后,总结了一下这类操做的核心:segmentfault

  1. 模式串主串进行比较数据结构

    • 从前日后比较
    • 从后往前比较
  2. 匹配时,比较主串模式串的下一个位置
  3. 失配时,优化

    • 模式串中寻找一个合适的位置spa

      * 若是找到,从这个位置开始与`主串`当前失配位置进行比较
      * 若是未找到,从`模式串`的头部与`主串`失配位置的下一个位置进行比较
    • 主串中找到一个合适的位置,从新与模式串进行比较

因此总的来讲,之因此会有这么多种匹配算法,本质上就是一些大神对第1步和第3步进行了优化,这个核心思路必定要紧紧的先记在脑子里,这样以后理解优化的匹配算法就不会一脸懵逼。翻译

算法介绍与分析

介绍

BF 算法,Brute-Force(暴力)法的简称,彻底没有优化,每次失配时从主串的下一个位置进行比较,直到比较结束。3d

分析

算法描述以下:code

  1. 模式串主串从前日后比较
  2. 匹配时,比较主串模式串的下一个位置
  3. 失配时,从主串下一个位置开始与模式串的头部从新开始比较

咱们假设有 主串 ABABBBAAABABABBA模式串 ABABABB
下面放五张图来理解一下这个过程:
QQ20200112-160741.pngblog

QQ20200112-161000.png

上面这两幅图,表现的是第1步和第2步,能够看出:字符串

  1. S[0]P[0] 开始从头日后比较
  2. 若是匹配,比较S[i++]S[j++]

QQ20200112-161423.png

QQ20200112-161548.png

上面这两幅图,则表现的时第3步,能够看出:

  1. 若是 S[i]P[j] 失配
  2. j = 0P[0] 也就是模式串头部开始与主串下一个位置S[i - (j - 1)]开始继续进行匹配

重复上述两步,直到下图彻底匹配或者找不到模式串为止

QQ20200112-162337.png

代码

思路仍是很好理解的,可是代码怎么写呢?
其实我一直以为刷 LeetCode 除了巩固与提升数据结构与算法的能力以外,最重要的就是训练一种把思路翻译成代码的能力,下面我来尝试翻译一下上述的算法思路。

一、先进行极端状况的排除

carbon.png

这个操做应该是刷题刷多了,像之前作数学题写“解”的操做

二、写出总体的结构

  1. 从算法的思路很容易看出,这里的“重复上诉两步”,明显是要翻译成循环操做
  2. 若是是循环,那么终止条件是什么,能够很快想到,只有两种终止状况:

    • 主串中没有找到 模式串的匹配,此时 i = haystack.length
    • 主串中找到了模式串的匹配,此时 j = needle.length
  3. 算法处理过程主要是两步,因此这里必定有一个分支结构

    • 匹配
    • 失配
  4. 若是没找到,直接 return -1 就行了,但要是找到了,应该怎么肯定那个 index 的值呢?根据上面成功的图,咱们能够发现,匹配的位置 8,是等于 主串的末尾 14 减去 模式串的末尾 6 获得的,也就是最后匹配的那个 index = i - j

carbon的副本.png

三、补充具体操做

根据算法分析里的描述,很容易知道

  1. 匹配,i++; j++; 比较各自的下一位
  2. 失配,i = i - (j - 1); j = 0;从新进行下一轮匹配

carbon的副本2.png

总结

至此,整个BF算法的分析与编写就完成了,虽然它是一个毫无优化的结构,可是体现出了全部字符串匹配算法的基本思想,计算机不是人,能够经过眼睛观察和大脑思考来进行定位,它只能经过一个一个字符的比较来进行断定,接下来的算法,就开始运用到一些骚操做来进行优化这个匹配的过程。

后记

“字符串匹配算法”是“重学数据结构与算法”系列笔记中的一个章节,细分为如下几个部分,以后会陆续填坑。

相关文章
相关标签/搜索