日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

分享一下字符串匹配BM算法学习心得。

發布時間:2025/4/14 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 分享一下字符串匹配BM算法学习心得。 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

字符串匹配BM(Boyer-Moore)算法學習心得

  BM算法 Boyer-Moore算法 的縮寫,是一種基于后綴比較的模式串匹配算法。BM算法在最壞情況下可以做到線性的,平均情況下是亞線性的(即低于線性)。這也是他在實際應用中優于KMP算法的一個原因吧。

  最近突然在看[柔性字符串匹配].[Flexible.Pattern.Matching.in.Strings](Gonzalo.Navarro,.Mathieu.Raffinot),想了解一下字符串匹配的一些算法,以前使用的算法基本都只是和ACM有關的,而且在單串匹配的情況下一般都只用KMP算法,而在這本書中對KMP算法的評價并不是很好,原因主要是出于工程上的“實用”上的原因吧。KMP算法雖然在理論上最壞復雜度也是線性的,可是在實際應用中并沒有那么多最壞情況,而且如果用于模式匹配的話,很多情況下模式串也是很短的。

  下面來說一說我寫這個的原因吧,我搞了兩年ACM嘛,現在看書肯定還是和ACM有一定關系的,而且很自然的會將一些事情和ACM中做對比的。[柔性字符串匹配]說KMP在實際應用中不好,那我就想反過來看一下在實際應用中比較好的算法在ACM中效果怎么樣了,最先看到的就是BM算法(當然在書中還看到了Shift-or 和Shift-and 算法,但由于長度限制差別太大,實在不具可比性,不過這兩個算法個人感覺是相當優雅的)。由于這本書太實用了,對于“不實用”的算法都只做基本介紹(對于KMP算法也一樣,只做了一點大概的介紹,其實我非常不明白為什么會出現這種現象,難道理論和應用的差別有這么大么?)。書上說原始BM算法在最壞情況下復雜度是O(n*m)的,O(n*m)的算法在ACM中必然是不“實用”的,但它說BM算法有兩個優化版本可以在最壞情況下也能達到線性的。這樣一來我覺得就有一定可比性了,于是就想仔細看一下BM算法。

  書上說的兩個算法是:the Boyer-Moore-Galil [Gal79] and the Turbo-BM[CGR92] algorithms。

  我找了找,也沒找到什么相關資料,但是回頭一想這個算法都出來這么久了,直接搜BM算法應該也能搜出優化過的BM算法吧。

  下面是我找到的一些文章。

?

字符串匹配那些事(一)

  這篇文章好像是淘寶的吧,其中沒有明確指出BM算法的時間復雜度。

M模式匹配算法原理(圖解)

  這篇文章對BM進行了大致的講解,文中分析到了時間復雜度,

  文中為:最好情況下的時間復雜度為O(n/m),最壞情況下時間復雜度為O(m·n)。

精確字符串匹配(BM算法)??BM 算法中“好后綴”預處理

  在第一篇文章中提到了時間復雜度:整個算法的時間復雜度最壞的情況是 O(m),m 是 T 的長度。

  可有一點我不明白,按這篇文章中的作法,好像并沒有對原始的BM算法進行優化,而原始的BM算法確實是O(m·n)的。

?

  又重新去搜論文了。

A Fast String Searching Algorithm?- The University of Texas at Austin

Boyer-Moore-Galil?[Gal79]?Z. Galil. On improving the worst case running time of the Boyer-Moore string searching algorithm. Communications of the ACM, 22(9):505–508, 1979.

  看了一下這兩篇論文,看一下第一篇,實在太長了(其實只有11頁但相對于第二篇只有4頁)。然后果斷看第二篇,雖然已經是三十多年前的論文了。

  在這里費話兩句,之前我因為《柔性字符串匹配》這本書說KMP不怎么實用,心里還感覺有點不爽,你說KMP不實用,那你拿一個實用且理論最壞復雜度為線性的算法讓我看看。再加上找了一天多也只有一些BM算法的原始版。看了上面的第二篇文章,實現了一下其中的算法并在POJ上試了試,果然沒問題。在這一刻我深深的折服于《柔性字符串匹配》了。這本書果然名副其實。值得推薦。

  好了,費話也就說這么多,接下來說點技術性的吧,看看Z. Galil. 是如何將BM的最壞情況復雜度降到線性的。在這里,我默認大家是明白BM算法原理的。加上上面已經有那么多文章是寫BM算法的了(如果需要,建議閱讀淘寶的那篇),我這里只討論的優化了。

  

  以下討論中,文本串用T表示,模式串用p表示。|S|表示字符串S的長度。默認情況下,n=|T|,m=|p|

?

  為什么原始的BM算法在最壞情況下是O(n*m)的呢?一個最簡單的實例就是 p=a^m,T=a^n。就是說模式串是由m個a組成,文本是由n個a組成,在這種情況下,找出所有匹配復雜度就是O(n*m)的。造成這種情況最主要的就是BM算法在向后滑動的時候對之前匹配過的字符的利用率并不高,不像KMP,一旦匹配過,就不會再回過頭再匹配一次,這也是我感覺KMP相當神的一點。
  在此之前先討論幾個概念,一個是字符串的周期性。
  直觀的理解就是類似:abcabcabcabc,aabaabaab...這樣的串,都是有周期性的。我們在這里認為這種模式串也具有周期性的——abcabcab,就是最一個重復單元是不完整的。這里的周期性指至少重復一次以上,這種串不算有周期性——abcdabc。隨便提一下,這樣的串不具有周期性——ababababc,這里的周期性是針對于整個字符串來說的。

  對于具用周期性的模式串,記模式串的最小正周期長度為ord。
  再引出一個定義:匹配塊,T中的一段匹配塊是一段連續的字符串,其中包含有匹配上的匹配串,并且這些匹配上的區域是相互重疊的并且盡可能向左右延伸。當然在匹配塊中不包含多余的字符。舉一個例子。(這里對匹配塊的定義不準確,大家明白這個意思就行了。)
    p = aba
    T = abababaabaaba
  其中前面一部分就是一個匹配塊:abababa,后面的abaaba不算,因為匹配上匹配串沒有相互重疊。
  基于以下幾點討論,我們可以對BM算法進行優化。

    (1)如果文本串中不含模式串,那么BM算法在最壞情況下的比較次數為7n次。
    (2)BM算法的最壞情況復雜度為O(n+r*m),其中n為|T|,m為|p|,r為p在T中出現次數。
    (3)如果在上式中r>2n/m,則p是具有周期性的。
    (4)如果p不具周期性,那么BM算法在最壞情況下是線性的。
    (5)記一個匹配塊中所有匹配上的位置為p0,p1,...,pk(以遞增方式排列),
       那么對于0<i<=k,pi - p(i-1)=ord。而且每個匹配塊中的匹配可以做到線性。
    (6)優化之后的BM' 算法是O(n)的。

  優化方法:每次成功匹配以后,向右移ord,并且在這種情況下只匹配那ord個字符。
  偽代碼如下:

優化部分偽代碼 1 last = 0;
2 for(k=0; k+|p|<=|T|; )
3 {
4 for(i=pn-1; i>=last && T[k+i]==p[i]; )
5 i--;
6 if( i<last )
7 { /// 成功匹配
8 last = |p| - ord;
9 k += ord;
10 }
11 else
12 { /// 匹配失敗
13 last = 0;
14 k += (BM算法中的移動距離);
15 }
16 }



  這里就是算法的核心了。這里 hust 有BM實現poj 3461的完整代碼。
  這個優化只要知道的話就很好做了,在已有的BM代碼上加兩行就實現了。
  這個改進之后的BM' 算法在最壞情況下是線性的。
  下面是相關說明,論文上也有證明。這里以比較直白的方式對其進行一些分析。


(1)如果文本串中不含模式串,那么BM算法在最壞情況下的比較次數為7n次。
    這一條我也不知道怎么證明的,這里默認他是正確的吧。論文上說比較復雜沒有介紹。

(2)BM算法的最壞情況復雜度為O(n+r*m),其中n為|T|,m為|p|,r為p在T中出現次數。
    這里我們把所有的r次完整匹配取出來,總共r*m次比較。這里我們想像用這r次匹配上的位置(取最左端)把T分割成了r+1個部分。對于前r個部分,我們還需要在其右端加上(m-1)字符。這里的r+1個文本串已經無法匹配上p了。所以這里可以直接使用(1)了。而這時的總長度約為(n+r*m),代入第一條可得總比較次數少于:
7*n + 8*r*m <- ( 7*(n+r*m) + r*m )

(3)如果在上式中r>2n/m,則p是具有周期性的。
    這里可以用鴿籠原理。先討論當r>n/m時,即r*m>n。所有匹配的長度之和已經大于了|T|,這時,至少有兩個匹配上的串是互相重疊的。這樣,r>2*n/m就很好理解了吧,r*(m/2)>n,至少存在兩次匹配上的串是互相重疊的,并且,重疊部分大于m/2。這代表了什么含意呢?想像一下,一個字符串,可以通過平移一小段距離,使重疊的那一部分互相匹配。這可以推出這個串是具有周期性的。

(4)如果p不具周期性,那么BM算法在最壞情況下也是線性的。
    這條可以用(3)的逆否命題得到:如果p不具有周期性,那么在上式中r<=2n/m。再代入(2)中表達式O(n+r*m)。可得此時BM算法復雜度O(3*n)即O(n)。

(5)記一個匹配塊中所有匹配上的位置為p0,p1,...,pk(以遞增方式排列)。那么對于0<i<=k,pi - p(i-1)=ord。
    這一點顯然吧。其實我并不是特別明白論文中特意指出這一點的意義何在。

(6)BM' 算法是O(n)的。
    在這一點的理解上,很接近第二步的分析。把所有的匹配塊提取出來,對于匹配塊來說匹配是線性的,匹配塊的總長是在O(n)級別的。這里需要說明一點的是匹配塊是可以相互重疊的,但重疊部分不會大于m/2。而在剩下部分的匹配依然是O(n)級別的,所以總的時間復雜度也是O(n)的。

?

  最后加一點關于(4)點的討論:我之前有一個錯誤的認識,我以為當p=b+a^m,T=a^n 時BM算法也是O(n*m)的,但我分析錯了一個地方,我以為當每次匹配到p的最左邊的b時,失敗后只向右跳一個字符,而實際情況是向右跳了串長這么多。對BM的理解不夠啊。

  附上poj測試圖,雖然從這里看BM算法跑得比kmp慢了一點,但我已經很滿足了。

            上面的兩份代碼是用BM實現的,下面兩份是用KMP實現的。

?

轉載于:https://www.cnblogs.com/a180285/archive/2011/12/15/BM_algorithm.html

《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

總結

以上是生活随笔為你收集整理的分享一下字符串匹配BM算法学习心得。的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。