理解字符串匹配KMP算法的一些細(xì)節(jié)

阮一峰的這篇文章啥酱,字符串匹配的KMP算法挡爵,能夠很好地幫助我們理解KMP的大致思路姆泻。如果需要從原理上更深入和全面的理解火窒,比如在text processing問題中常用的自動(dòng)機(jī)表示硼补,可以參考UCI的一個(gè)Lecture Note

網(wǎng)上有各種實(shí)現(xiàn)熏矿,這里選取比較容易理解并且合乎邏輯的一則來(lái)討論已骇。

源自geeksforgeeks离钝。

# Python program for KMP Algorithm
def KMPSearch(pat, txt):
    M = len(pat)
    N = len(txt)
 
    # create lps[] that will hold the longest prefix suffix 
    # values for pattern
    lps = [0]*M
    j = 0 # index for pat[]
 
    # Preprocess the pattern (calculate lps[] array)
    computeLPSArray(pat, M, lps)
 
    i = 0 # index for txt[]
    while i < N:
        if pat[j] == txt[i]:
            i+=1
            j+=1
 
        if j==M:
            print "Found pattern at index " + str(i-j)
            j = lps[j-1]
 
        # mismatch after j matches
        elif i < N and pat[j] != txt[i]:
            # Do not match lps[0..lps[j-1]] characters,
            # they will match anyway
            if j != 0:
                j = lps[j-1]
            else:
                i+=1
 
def computeLPSArray(pat, M, lps):
    len = 0 # length of the previous longest prefix suffix
 
    lps[0] # lps[0] is always 0
    i = 1
 
    # the loop calculates lps[i] for i = 1 to M-1
    while i < M:
        if pat[i]==pat[len]:
            len+=1
            lps[i] = len
            i+=1
        else:
            if len!=0:
                # This is tricky. Consider the example AAACAAAA
                # and i = 7
                len = lps[len-1]
 
                # Also, note that we do not increment i here
            else:
                lps[i] = 0
                i+=1
 
txt = "ABABDABACDABABCABAB"
pat = "ABABCABAB"
KMPSearch(pat, txt)  

比較需要理解的,是j = lps[j-1]len = lps[len-1]這樣兩處褪储。

首先第一個(gè)卵渴,j = lps[j-1]。當(dāng)j==M鲤竹,即找到匹配時(shí)浪读,將pattern的cursor也就是j移動(dòng)到lps[j-1]處。為什么不是lps[j]處呢辛藻,其實(shí)很容易理解碘橘,因?yàn)閜attern和lps數(shù)組都是zero based,lps是longest proper prefix which is also suffix吱肌,那么從零開始痘拆,應(yīng)當(dāng)是要有-1存在的。同理氮墨,不匹配的情況中纺蛆,j != 0時(shí),j = lps[j-1]规揪。

第二個(gè)桥氏,computeLPSArray方法中的len = lps[len-1]。既然都不匹配了猛铅,那么該處的lps不是應(yīng)該變成0嗎识颊?要注意的是,在這個(gè)方法中奕坟,pattern字符串(數(shù)組)的cursor是i祥款,而不是len,并且月杉,len = lps[len-1]之后刃跛,i并沒有變化。在某些情況苛萎,比如AAACAA桨昙,當(dāng)i==3的時(shí)候,的確該處的lps是0腌歉,但是len并不表示某處的lps蛙酪,而是一個(gè)中間量,用于表示lps翘盖。這里桂塞,如果pat[i]==pat[len]或者len一直不滿足,那么len = lps[len-1]將一直執(zhí)行馍驯。因?yàn)?code>lps[0]始終是0阁危,所以循環(huán)肯定是會(huì)終止的玛痊。len = lps[len-1]在這里到底是什么含義呢?其實(shí)可以把len理解成一個(gè)對(duì)于前綴的cursor狂打,讓這個(gè)cursor往前(往index 0)移動(dòng)擂煞,這樣在下一次pat[i]==pat[len]的比較,前綴cursor回退了趴乡。

舉例來(lái)說对省,在AAACAAAAA這個(gè)pattern中,當(dāng)剛剛運(yùn)行到i==7時(shí)晾捏,len==lps[6]==3官辽,這個(gè)時(shí)候比較pat[3]字符C和pat[7]字符A,不相等粟瞬。所以我們自然而然地想要減小前綴再比較同仆。而這個(gè)過程,就是回退前綴的cursor裙品,表達(dá)出來(lái)俗批,也就是len=lps[len-1]

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末市怎,一起剝皮案震驚了整個(gè)濱河市岁忘,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌区匠,老刑警劉巖干像,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異驰弄,居然都是意外死亡麻汰,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門戚篙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)五鲫,“玉大人,你說我怎么就攤上這事岔擂∥晃梗” “怎么了?”我有些...
    開封第一講書人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵乱灵,是天一觀的道長(zhǎng)塑崖。 經(jīng)常有香客問我,道長(zhǎng)痛倚,這世上最難降的妖魔是什么规婆? 我笑而不...
    開封第一講書人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上聋呢,老公的妹妹穿的比我還像新娘苗踪。我一直安慰自己颠区,他們只是感情好削锰,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著毕莱,像睡著了一般器贩。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上朋截,一...
    開封第一講書人閱讀 51,624評(píng)論 1 305
  • 那天蛹稍,我揣著相機(jī)與錄音,去河邊找鬼部服。 笑死唆姐,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的廓八。 我是一名探鬼主播奉芦,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼剧蹂!你這毒婦竟也來(lái)了声功?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤宠叼,失蹤者是張志新(化名)和其女友劉穎先巴,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體冒冬,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡伸蚯,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了简烤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片朝卒。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖乐埠,靈堂內(nèi)的尸體忽然破棺而出抗斤,到底是詐尸還是另有隱情,我是刑警寧澤丈咐,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布瑞眼,位于F島的核電站,受9級(jí)特大地震影響棵逊,放射性物質(zhì)發(fā)生泄漏伤疙。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望徒像。 院中可真熱鬧黍特,春花似錦、人聲如沸锯蛀。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)旁涤。三九已至翔曲,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間劈愚,已是汗流浹背瞳遍。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留菌羽,地道東北人掠械。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像注祖,于是被迫代替她去往敵國(guó)和親猾蒂。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355

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