【重學數據結構與算法(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算法的分析與編寫就完成了,雖然它是一個毫無優化的結構,可是體現出了全部字符串匹配算法的基本思想,計算機不是人,能夠經過眼睛觀察和大腦思考來進行定位,它只能經過一個一個字符的比較來進行斷定,接下來的算法,就開始運用到一些騷操做來進行優化這個匹配的過程。

後記

「字符串匹配算法」是「重學數據結構與算法」系列筆記中的一個章節,細分爲如下幾個部分,以後會陸續填坑。

相關文章
相關標籤/搜索