KMP算法心得

在介紹kmp算法之前,我想先簡單介紹一下Brute-Force算法,這是一個(gè)回溯的字符串模式匹配算法,是一個(gè)簡單暴力狂!

1-1. Brute-Force算法分析

由上圖的匹配思想,主要代碼如下:

public static int indexOf(String target, String pattern){
    
    int i = 0,j = 0;

    while(i < target.length() - pattern.length()){
        
        if(target.charAt(i+j) == pattern.charAt(j)){
            j++;
        }else{
            i++;
            j = 0;
        }
        if(j == pattern.length()){
            return i;
        }
    }
    return -1;
}

很明顯,當(dāng)匹配不成功時(shí),目標(biāo)串每次向前移動(dòng)一位,模式串每次從P0開始重新匹配,雙方都存在回溯現(xiàn)象。在上圖中可以看出最差的情況: 每次匹配比較M次,比較了N - M + 1 次,比較總數(shù)是 M*(N - M + 1),由于M << N,所以時(shí)間復(fù)雜度O(M * N) 。

下面分析下Brute-Force算法的缺點(diǎn):

1-2. Brute-Force算法缺點(diǎn)

下面就著重講一下KMP算法:

  1. 算法描述:

    核心是找到模式串中的k( 0 <=k < j) 滿足"P0...Pk-1" = "Pj-k...Pj-1" = "Ti-k...Ti-1"  (當(dāng)Pj != Ti時(shí)),則模式串從Pk開始遍歷。
    

所以問題就轉(zhuǎn)化為:找到串"P0...Pj-1"相同的前綴子串和后綴子串的長度k。

1-3. KMP算法描述
  1. 求next數(shù)組
1-4. next公式

根據(jù)上圖的模式串"abcabc",可以得到next數(shù)組(注意在"P0...Pj-1"中尋找)

j 0 1 2 3 4 5
模式串 a b c a b c
next[j] -1 0 0 0 1 2
  1. 計(jì)算next數(shù)組的算法

由next數(shù)組的定義可以:

    1. next[0] = -1;
  • 2.對于任意的j (0<=j <m ) next[j] < j;
    1. 若next[j] = k 說明在子串"P0...Pj-1"中存在相同的前綴子串和后綴子串,"P0...Pk-1" = "Pj-k...Pj-1" (0=<k<j,k取最大值);
    1. 對于next[j+1]而言,判斷"P0...Pj"子串中,是否存在"P0...Pk" = "Pj-k...Pj-1Pj"的問題,可以分解為 :
        1. 是否存在"P0...Pk-1" = "Pj-k...Pj-1"的問題;
        1. Pk == Pj的問題;

很符合動(dòng)態(tài)規(guī)劃(Dynamic Programming)的問題,把多階段過程轉(zhuǎn)化為一系列單階段問題,利用各階段之間的關(guān)系,逐個(gè)求解,很像分治法。
同時(shí)個(gè)人認(rèn)為很像高考數(shù)列的相關(guān)問題 ---- 數(shù)學(xué)歸納法。

某個(gè)數(shù)列 An

  1. An = K (常數(shù));
  2. 假設(shè)前N項(xiàng)滿足: An = f(n) (某個(gè)函數(shù)式);
  3. 如果第N+1項(xiàng) 滿足 An+1 = f(n+1),則An = f(n) 等式成立。

綜上所述該動(dòng)態(tài)規(guī)劃的遞推公式:

D(j+1) = max(D(j)) + (Pk == Pj ? 1 : 0)

  1. 改進(jìn)next數(shù)組

在上圖1-3中 Pk = Pj , Ti != Pj => Pk != Ti 則完全沒有必要回溯到Pk開始比較,直接從P0開始,所以假如next[j] = k 且 Pk = Pj 則 next[j] = next[k];

  1. KMP核心代碼
private static int[] getNext(String pattern){

        int j = 0,k = -1;
        int[] next = new int[pattern.length()];
        next[0] = -1;
        while(j < pattern.length() - 1){
            if(k == -1 || pattern.charAt(j) == pattern.charAt(k)){
                j++;
                k++;
                //改進(jìn)next數(shù)組
                if(pattern.charAt(j) != pattern.charAt(k)){
                    next[j] = k;
                }else{
                    next[j] = next[k];
                }
            }else{
                k = next[k];
            }
        }
        return next;
    }
    public static int indexOf(String target, String pattern){
        
        int i = 0,j = 0;
        
        int[] next = getNext(pattern);
        
        while(i < target.length()){
            
            if(j == -1 || target.charAt(i) == pattern.charAt(j)){
                
                i++;
                j++;
            }else{
                j = next[j];
            }
            if(j == pattern.length()){
                
                return i - j;
            }
        }
        return -1;
    }
  1. KMP算法分析
1-5. KMP算法分析

時(shí)間復(fù)雜度O(M + N) ,當(dāng)M<<N或者比較次數(shù)少(匹配的成功率比較高),時(shí)間復(fù)雜度O(N)。

以上是本人對KMP算法的理解,歡迎大家指正和交流,謝謝!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,431評論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,637評論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,555評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,900評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,629評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,976評論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,976評論 3 448
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,139評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,686評論 1 336
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,411評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,641評論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,129評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,820評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,233評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,567評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,362評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,604評論 2 380

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