算法背景:
BF(Brute Force)算法,是一種在字符串匹配的算法中,比較符合人類自然思維方式的方法,即對源字符串和目標字符串逐個字符地進行比較,直到在源字符串中找到完全與目標字符串匹配的子字符串,或者遍歷到最后發現找不到能匹配的子字符串。算法思路很簡單,但也很暴力。
算法原理:
假設源字符串為“非常地非常地非常地喜歡你”,我們想從中尋找目標字符串“非常地非常地喜歡”,則BF算法的過程可以表述如下:
第1輪:將源字符串和目標字符串對齊,並下標0開始逐個向后比較每個字符。結果發現雙方的第1個字符都是“非”、第2個字符都是“常”、……,但到了第7個字符時發現不一致:源字符串為“非”、目標字符串為“喜”,因此這一輪匹配不成功。
第2輪:將目標字符串整體向后移動1個字符的位置(即將目標字符串的第1個字符與源字符串的第2個字符對齊),並開始逐個向后比較每個字符,結果發現兩個字符串的第1個字符就不一致,因此這一輪匹配也不成功。
第3輪:類似地,將目標字符串整體向后移動1個字符的位置(即將目標字符串的第1個字符與源字符串的第3個字符對齊),並開始逐個向后比較,結果發現兩個字符串的第1個字符就不一致,因此這一輪匹配也不成功。
第4輪:這一輪終於發現,目標字符串的每個字符都能和源字符串對應起來,匹配成功!因此算法結束並根據需要返回相應的信息(比如返回這一輪源字符串遍歷起始點的位置下標3)
算法實現:
BF算法的python實現如下:
1 #!/usr/bin/env python 2 #-*- coding: utf-8 -*- 3 import sys 4 import pdb 5 6 reload(sys) 7 sys.setdefaultencoding('utf-8') 8 9 10 class BruteForce(object): 11 """BF算法 12 成員變量: 13 str_s: 源字符串 14 str_t: 目標字符串 15 """ 16 def __init__(self, str_s, str_t): 17 self.str_s = str_s 18 self.str_t = str_t 19 20 def run(self): 21 """完全匹配則返回源字符串匹配成功的起始點的下標,否則返回-1 22 """ 23 base = 0 # 記錄源字符串與目標字符串對齊的基准點 24 len_s = len(self.str_s) 25 len_t = len(self.str_t) 26 27 while base + len_t <= len_s: 28 step = 0 29 while step < len_t: 30 if str_t[step] == self.str_s[base + step]: 31 # 當前字符相同,則繼續比較下一個字符 32 step += 1 33 continue 34 # 當前字符不相同,則結束次輪比較,更新base基准位置,啟動下一輪比較 35 base += 1 36 break 37 # 完全匹配成功,算法結論,返回匹配成功的基准點位置下標 38 if step == len_t: 39 return base 40 # 遍歷了所有情況,最終匹配失敗,返回-1 41 return -1 42 43 44 if __name__ == '__main__': 45 str_s = u"非常地非常地非常地喜歡你" 46 str_t = u"非常地非常地喜歡" 47 model = BruteForce(str_s, str_t) 48 print model.run()
復雜度分析:
時間復雜度:
假設源字符串長度為m,目標字符串長度為n,則:
最好情況下是第一輪就成功匹配,則時間復雜度為O(n);
最壞情況下是遍歷到最后才成功匹配,或者遍歷到最后發現匹配不成功,則時間復雜度為O(n*(m-n+1)),一般實際使用時m >> n,所以可以認為趨近於O(m*n);
空間復雜度:
由於不需要額外的存儲空間,所以空間復雜度為O(1)
算法評估:
整個算法其實就循環執行如下兩個步驟:
一、從每一輪的基准點開始比較兩個字符串;
二、如發現不能完全匹配目標字符串,將目標字符串向后挪動一個字符的位置(即更新基准點);
如果想優化算法性能,那就簡單分析一下:
步驟一基本沒有優化的空間:兩個字符串比較就是需要從前向后逐個字符看是否匹配;
步驟二可能有優化的空間:每輪發現不匹配時,目標字符串只能向后挪動一個字符的距離,所以會想到能否多往后挪動幾個字符的距離?這樣不就減少了步驟一比較的輪次數,從而加快速度了嗎?這基本就是KMP算法的思路,下一篇《KMP算法》會詳細介紹。