字符串匹配 - Sunday算法

背景

提起字符串匹配,可能很多人都會(huì)想到KMP算法 O(m+n)奖亚,但是其實(shí)KMP并不常用淳梦,因?yàn)橐廊皇锹模S玫钠鋵?shí)是BM算法 O(m/n)(Boyer-Moore算法)昔字,這就是很多文本編輯器的查找功能采用的算法谭跨,而Sunday算法是在其之上又做了一些改動(dòng)。下面我給大家簡(jiǎn)單介紹下Sunday算法與BM算法針對(duì)于KMP算法的差異點(diǎn)李滴。

思路

先說(shuō)下BM算法

首先的區(qū)別,與KMP從前往后掃描模式串不同蛮瞄,BM算法是從后往前對(duì)模式串進(jìn)行掃描與主串進(jìn)行匹配的
其核心就是兩個(gè)啟發(fā)策略:

(1)壞字符算法
當(dāng)出現(xiàn)一個(gè)壞字符時(shí), BM算法向右移動(dòng)模式串, 讓模式串中最靠右的對(duì)應(yīng)字符與壞字符相對(duì)所坯,然后繼續(xù)匹配。壞字符算法有兩種情況挂捅。

Case1:模式串中有對(duì)應(yīng)的壞字符時(shí)芹助,讓模式串中最靠右的對(duì)應(yīng)字符與壞字符相對(duì)(PS:BM不可能走回頭路,因?yàn)槿羰腔仡^路,則移動(dòng)距離就是負(fù)數(shù)了状土,肯定不是最大移動(dòng)步數(shù)了)无蜂,如下圖。


Case1

Case2:模式串中不存在壞字符蒙谓,那么直接右移整個(gè)模式串長(zhǎng)度這么大步數(shù)斥季,如下圖。

Case2

(2)好后綴算法
如果程序匹配了一個(gè)好后綴, 并且在模式串中還有另外一個(gè)相同的后綴(參見case1)或后綴的部分(參見case2), 那把下一個(gè)后綴或部分移動(dòng)到當(dāng)前后綴位置累驮。即酣倾,模式串的后u個(gè)字符和主串都已經(jīng)匹配了,但是接下來(lái)的一個(gè)字符不匹配谤专,如果說(shuō)后u個(gè)字符在模式串其他位置也出現(xiàn)過(guò)或部分出現(xiàn)躁锡,我們將模式串右移到前面的u個(gè)字符(參見case1)或部分和最后的u個(gè)字符或部分相同(參見case2)的位置,如果說(shuō)后u個(gè)字符在模式串其他位置完全沒(méi)有出現(xiàn)置侍,那么就直接右移整個(gè)模式串(參見case3)映之,如下圖所示:

Case1:模式串中有子串和好后綴完全匹配,則將最靠右的那個(gè)子串移動(dòng)到好后綴的位置繼續(xù)進(jìn)行匹配蜡坊。

Case1

Case2:如果不存在和好后綴完全匹配的子串杠输,則在好后綴中找到具有如下特征的最長(zhǎng)子串,使得P[m-s…m]=P[0…s]。

Case2

Case3:如果完全不存在和好后綴匹配的子串算色,則右移整個(gè)模式串抬伺。

(3)移動(dòng)規(guī)則
BM算法的移動(dòng)規(guī)則是:
BM算法是每次向右移動(dòng)模式串的距離是 MAX(shift(好后綴),shift(壞字符))灾梦,即按照好后綴算法和壞字符算法計(jì)算得到的最大值峡钓。

缺點(diǎn)

BM算法與KMP思想類似,但是更好了利用了預(yù)處理數(shù)組若河,使得更有效率能岩,但是模式串的預(yù)處理數(shù)組也變得相對(duì)更加復(fù)雜,所以當(dāng)面臨較小場(chǎng)景時(shí)萧福,并不一定適合選用BM算法拉鹃。

優(yōu)點(diǎn)
  • 時(shí)間復(fù)雜度
KMP O(m+n)
BM O(m/n) - O(m*n)
  • 思維優(yōu)勢(shì)
    BM算法從后往前掃描模式串使得它更好的利用了“后綴”,BM算法的啟發(fā)策略也使得模式串可以更加有效率的移動(dòng)鲫忍,在面臨實(shí)際使用中的較大匹配場(chǎng)景時(shí)膏燕,效率提高明顯。

BM算法的具體實(shí)現(xiàn)悟民,例如好后綴算法和壞字符算法 模式串的預(yù)處理數(shù)組如何實(shí)現(xiàn)坝辫?
請(qǐng)移步某前輩的文章: grep之字符串搜索算法Boyer-Moore由淺入深,這里不細(xì)說(shuō)了射亏,只介紹下核心差異點(diǎn)近忙。

知道了BM算法竭业,下面我們來(lái)說(shuō)Sunday算法

Sunday算法

Sunday算法是從前往后掃描模式串的,其思路更像是對(duì)于“壞字符”策略的升華及舍。關(guān)注的是主串中參與匹配的最末字符(并非正在匹配的)的下一位未辆,稍后看圖更容易理解
Sunday算法只有一個(gè)啟發(fā)策略

Case1:當(dāng)遇到不匹配的字符時(shí),如果關(guān)注的字符沒(méi)有在模式串中出現(xiàn)則直接跳過(guò)
移動(dòng)位數(shù) = 子串長(zhǎng)度 + 1锯玛;

Case1

Case2: 當(dāng)遇到不匹配的字符時(shí)咐柜,如果關(guān)注的字符在模式串中也存在時(shí),其
移動(dòng)位數(shù) = 模式串長(zhǎng)度 - 該字符最右出現(xiàn)的位置(以0開始)
或者移動(dòng)位數(shù) = 模式串中該字符最右出現(xiàn)的位置到尾部的距離 + 1
看下例子:

Case2

策略是很清晰簡(jiǎn)單的更振,但是想一下就可以發(fā)現(xiàn)炕桨,這個(gè)算法缺點(diǎn)也很明顯:

缺點(diǎn)

如果是下面這個(gè)情況,會(huì)怎么樣肯腕?
主串:baaaabaaaabaaaabaaaa
子串:aaaaa
沒(méi)錯(cuò)献宫,這個(gè)時(shí)候,效率瞬間變成了O(m*n)
Sunday算法的移動(dòng)是取決于子串的实撒,這一點(diǎn)跟BM算法沒(méi)什么區(qū)別姊途,當(dāng)這個(gè)子串重復(fù)很多的時(shí)候,就會(huì)非常糟糕了知态。大家知道這一點(diǎn)捷兰,有所取舍就好

優(yōu)點(diǎn)
  • 時(shí)間復(fù)雜度
KMP O(m+n)
BM O(m/n) - O(m*n)
Sunday O(m/n) - O(m*n)
實(shí)際使用中 Sunday算法比BM算法略優(yōu)
  • 思維優(yōu)勢(shì)
    我理解Sunday算法優(yōu)在,它的思路很簡(jiǎn)單负敏,很清晰贡茅,而現(xiàn)實(shí)生活的實(shí)際場(chǎng)景中,又恰恰能較好的規(guī)避它的缺點(diǎn)其做,使得它能夠大大增加匹配效率顶考。

代碼

def sunday_search(self, haystack: str, needle: str) -> int:
        if not needle:
            return 0

        offset = {}
        n_l = len(needle)

        for i in range(n_l):
            offset[needle[i]] = n_l - i

        i, j, h_l = 0, 0, len(haystack)

        while i <= h_l - n_l:
            j = 0

            while haystack[i + j] == needle[j]:
                j += 1
                if j == n_l:
                    return i

            if i + n_l == h_l:
                return -1

            if haystack[i + n_l] in offset:
                i += offset[haystack[i + n_l]]
            else:
                i += n_l + 1

        return -1

以上,歡迎大家討論妖泄,共同進(jìn)步


歡迎大家關(guān)注我的公眾號(hào)


半畝房頂
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末驹沿,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子蹈胡,更是在濱河造成了極大的恐慌渊季,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,454評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件罚渐,死亡現(xiàn)場(chǎng)離奇詭異却汉,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)荷并,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門病涨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人璧坟,你說(shuō)我怎么就攤上這事既穆。” “怎么了雀鹃?”我有些...
    開封第一講書人閱讀 157,921評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵幻工,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我黎茎,道長(zhǎng)囊颅,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,648評(píng)論 1 284
  • 正文 為了忘掉前任傅瞻,我火速辦了婚禮踢代,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘嗅骄。我一直安慰自己胳挎,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,770評(píng)論 6 386
  • 文/花漫 我一把揭開白布溺森。 她就那樣靜靜地躺著慕爬,像睡著了一般。 火紅的嫁衣襯著肌膚如雪屏积。 梳的紋絲不亂的頭發(fā)上医窿,一...
    開封第一講書人閱讀 49,950評(píng)論 1 291
  • 那天,我揣著相機(jī)與錄音炊林,去河邊找鬼姥卢。 笑死,一個(gè)胖子當(dāng)著我的面吹牛渣聚,可吹牛的內(nèi)容都是我干的独榴。 我是一名探鬼主播,決...
    沈念sama閱讀 39,090評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼饵逐,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼括眠!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起倍权,我...
    開封第一講書人閱讀 37,817評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤掷豺,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后薄声,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體当船,經(jīng)...
    沈念sama閱讀 44,275評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,592評(píng)論 2 327
  • 正文 我和宋清朗相戀三年默辨,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了德频。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,724評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡缩幸,死狀恐怖壹置,靈堂內(nèi)的尸體忽然破棺而出竞思,到底是詐尸還是另有隱情,我是刑警寧澤钞护,帶...
    沈念sama閱讀 34,409評(píng)論 4 333
  • 正文 年R本政府宣布盖喷,位于F島的核電站,受9級(jí)特大地震影響难咕,放射性物質(zhì)發(fā)生泄漏课梳。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,052評(píng)論 3 316
  • 文/蒙蒙 一余佃、第九天 我趴在偏房一處隱蔽的房頂上張望暮刃。 院中可真熱鬧,春花似錦爆土、人聲如沸椭懊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)灾搏。三九已至,卻和暖如春立润,著一層夾襖步出監(jiān)牢的瞬間狂窑,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工桑腮, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留泉哈,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,503評(píng)論 2 361
  • 正文 我出身青樓破讨,卻偏偏與公主長(zhǎng)得像丛晦,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子提陶,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,627評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容

  • 字符串匹配(查找)算法是一類重要的字符串算法(String Algorithm)烫沙。有兩個(gè)字符串, 長(zhǎng)度為m的hay...
    曾會(huì)玩閱讀 3,816評(píng)論 4 8
  • Sunday算法 匹配原理 從前往后匹配,如果遇到不匹配情況隙笆,則查看母串S中參與匹配的最后一位的下一位字符锌蓄,記做C...
    HITMiner閱讀 336評(píng)論 0 1
  • ??在文本處理中,關(guān)鍵字匹配是一個(gè)十分常用且重要的功能撑柔。關(guān)鍵字稱為模式串瘸爽,在文本T中尋找模式串P出現(xiàn)的所有出現(xiàn)的位...
    老羊_肖恩閱讀 4,505評(píng)論 1 4
  • 字符串匹配算法之Sunday算法 背景 我們第一次接觸字符串匹配,想到的肯定是直接用2個(gè)循環(huán)來(lái)遍歷铅忿,這樣代碼雖然簡(jiǎn)...
    houskii閱讀 9,867評(píng)論 10 25
  • 字符串匹配KMP算法詳解 1. 引言 以前看過(guò)很多次KMP算法剪决,一直覺(jué)得很有用,但都沒(méi)有搞明白,一方面是網(wǎng)上很少有...
    張晨輝Allen閱讀 2,390評(píng)論 0 3