GIF警告!讓你搞懂到底什麼是KMP算法

2021-02-20 圖解面試算法

你可能聽過KMP這個名詞,先不用管KMP是什麼,看看下面的問題:

給你一個字符串"jail",讓你在「abjacalisjaisnfljailnafa」中尋找該字符串是否存在。

第一次看到這道題的時候,上來就是一通暴力匹配,思路也很容易理解

該題暴力解法的基本思路是:用兩個指針分別指向字符串P和T的首個字符

一旦兩個指針指向的字符不同,字符串T的首個字符和P中的下一個位置重新開始匹配

重複上述兩個步驟,直到兩個指針任意一個指針走到了字符串的結尾,循環截止;

如果T的指針的大小等於T的長度,說明匹配成功,否則,匹配失敗。

問題是可以解決,但是,其中很多步驟都是重複的,因為一旦匹配失敗,T字符又要從頭開始匹配,這樣是不是浪費了很多時間?

而生活中我們使用字符串匹配的地方是非常多的

我們所用的IDE、office辦公軟體、文本編輯器等等非常多的軟體中是不是都包含了文本查找文本替換這些功能呢?

這個時候,KMP算法橫空出世

圖片中的內容截取於維基百科

說了這麼多,這個算法究竟是如何進行字符串查找的呢?

首先,該算法需要在開始匹配之前收集足夠的「信息」,用於在匹配過程中給出「指導意見

這個「信息」指,根據待查找字符串T建立的一張

但是最長公共前後綴長度如何求呢?

如果長的字符串不容易得出答案,那我們嘗試從最短的字符串看看:

a:很明顯,它的公共前後綴長度為0

ab:公共前後綴長度為0,因為a != b

aba:公共前後綴長度為1,也是最長的,因為前後都有一個a

abab:最長公共前後綴長度為2

ababc:最長公共前後綴長度為0

比較abaabab,你能發現什麼?

aba的基礎上加了一個字符,這個字符和第一個a後面的字符相同,所以在aba的基礎上,abab的最差公共前後綴長度為2

而在abab的基礎上加了一個c字符,整個字符串的公共前後綴的長度就變為了0,這是因為c字符和abab中的任何字符並不相等

發現規律了嘛?

從最小的開始比較,因為當一個字符作為子串的時候,公共前後綴的長度一定是0,就不用計算了,從第二個開始,也就是從ab開始,我們比較0位置和1位置是否相同,相同的話最長公共前後綴就是1,否則就為0

然後繼續看aba,比較新添加的字符和上一次求出的公共前後綴長度值的位置的字符是否相同,相同,用求出的上一個子串的公共前後綴長度加上1,aba的最長公共前後綴長度就為1

abab,還是上述步驟,看新添加字符和第[上一個子串的最長公共前後綴長度]個字符,也就是1位置和3位置,相同,那麼abab子串的最長公共前後綴長度=1+上一個子串的最長公共前後綴長度

那麼如何根據這個來進行加速匹配呢?

匹配的過程中一定是按照相應的規則進行匹配的,對應的,table中的值可是大有用處的,先不說那麼多概念,最直觀的感受一下KMP算法是如何進行匹配的吧

上面的動畫中,我們讓字符串T字符串P中進行匹配,如果在P中找到了T的存在,返回true,否則返回false;

匹配的規則還是一個字符對一個字符進行匹配,但是KMP算法神奇的地方就在於,當兩個字符沒有匹配成功的時候所採取的策略,這個策略並不是和暴力解法那樣:一旦一個字符沒有匹配成功,不管之前有多少個匹配成功,直接從頭再來。

這個策略依託的就是我們最開始建立的最長公共前後綴表

兩個字符匹配的時候,相安無事,兩個指針都往後移動;

一旦兩個字符沒有匹配成功,首先要做的就是拿到T指針的位置在table表中找出對應位置的值這個值就是我們下一次要進行匹配的T字符串中起始位置

代碼:
public boolean kmp(String resource, String target) {
    int len = target.length();
    if (len < 1) return false;
    //確定最長公共前後綴表
    int[] preTable = new int[len];
    commonPrefix(target,preTable);
    int i = 0,j = 0;//i指向resource  j指向target
    while (i < resource.length() && j < target.length()) {
        //如果兩個指針指向的字符不同
        if (resource.charAt(i) != target.charAt(j)) {
            //根據最長公共前後綴表中j所在位置的值移動指針
            //如果小於0,resource中的指針後移,j不動
            if (preTable[j] < 0) {
                i++;
            } else {
                //否則將指針j的位置修改為最長公共前後綴表中j位置對應的值(重新確定匹配位置)
                j = preTable[j];
            }
        } else {
            i++;
            j++;
        }
    }
    //如果指針j的長度等於target長度說明匹配成功,否則,失敗
    return j == target.length();
}
//獲取target字符串的最長公共前後綴表
private void commonPrefix(String target, int[] preTable) {
    int n = target.length() - 1;
    if (n > 0 && n < 2) {
        preTable[0] = -1;
        return;
    }
    //為了編碼方便
    preTable[0] = -1;
    //一個字符的最長公共前後綴長度一定是0
    preTable[1] =  0;
    int index = 2;
    int j = 1;
    while (j < n) {
        if (target.charAt(preTable[index - 1]) == target.charAt(j)) {
            preTable[index] = preTable[index - 1] + 1;
        } else {
            preTable[index] = 0;
        }
        index++;
        j++;
    }
}

感謝大家的閱讀,如果對文中內容有不同見解,希望不吝賜教。

相關焦點

  • KMP算法詳解
    kmp算法又稱「kmp」算法,是一個效率非常高的字符串匹配算法
  • KMP算法文章合集
    –KMP算法理解(python) KMP的next數組求法詳解 KMP算法詳解 KMP算法(代碼+圖解證明) 算法之字符串匹配的KMP算法1 KMP算法解決字符串匹配問題 字符串的模式匹配(KMP)算法 字符串匹配KMP算法的理解(詳細) python實現kmp算法(學不會你噴我)
  • 教你初步了解KMP算法
    本文由簡單的字符串匹配算法開始,再到KMP算法,由淺入深,教你從頭到尾徹底理解KMP算法。來看算法導論一書上關於此字符串問題的定義:假設文本是一個長度為n的數組T[1...n],模式是一個長度為m<=n的數組P[1....m]。進一步假設P和T的元素都是屬於有限字母表Σ.中的字符。
  • 漫畫:什麼是KMP算法?
    ,利用哈希值進行比較的RK算法,以及儘量減少比較次數的BM算法,沒看過的小夥伴可以點擊下方連結:1.BF算法和RK算法2. BM算法如果沒時間細看也沒關係,就讓我帶著大家簡單梳理一下。首先,給定 「主串」 和 「模式串」 如下:BF算法是如何工作的?
  • 動態規劃之 KMP 算法詳解
    kmp算法因為 KMP 算法知道字符 b 之前的字符 a 都是匹配的,所以每次只需要比較字符 b 是否被匹配就行了。 = new KMP("aaab");int pos1 = kmp.search("aaacaaab"); int pos2 = kmp.search("aaaaaaab"); 二、狀態機概述為什麼說 KMP 算法和狀態機有關呢?
  • 輕鬆理解什麼是KMP算法
    KMP算法 內部涉及到的數學原理與知識太多,本文只會對 KMP算法 的運行過程、 部分匹配表 、next數組 進行介紹,如果理解了這三點再去閱讀其它有關 KMP算法 的文章肯定能有個清晰的認識。以下的文字描述請結合視頻動畫來閱讀~定義Knuth-Morris-Pratt 字符串查找算法,簡稱為 KMP算法,常用於在一個文本串 S 內查找一個模式串 P 的出現位置。
  • 亞馬遜A9算法到底是什麼?一文教你讀懂
    那亞馬遜如何來判斷你的產品是不是符合以上幾個標準呢?符合以上條件的產品又會有哪些「福利」呢?這裡我們就需要引入亞馬遜的搜索核心——A9算法!什麼是A9算法簡單來講,為了提高產品的轉化,也為了方便服務消費者,亞馬遜會精準對客戶的產品搜索、購買等行為進行記錄和分析,確保客戶能儘快找到「想要購買的產品」。
  • KMP算法圖文詳解
    KMP算法是解決字符串匹配的常用算法之一,也就是在主串(比如aabbccdd)中的子串(bc)定位問題。子串稱為P,如果它在一個主串稱為T中出現,就返回它的具體位置,我們先來看看普通的字符串匹配是怎麼做的最基礎的匹配思路:從左到右一個個匹配,如果這個過程中有某個字符不匹配,將子串向右移動一位,繼續從左到右一一匹配。
  • 8張GIF圖片認識AR應用
    1、2D圖片識別(視頻)http://blog.metaio.com/wp-content/uploads/2015/02/PicturestoLife.1.88M.gif2D圖片識別是許多AR應用的算法基礎。在這個應用中藝術家使用2D圖片跟蹤技術將他的作品注入生命,作品中的事物動了起來。
  • 五大常用算法:一文搞懂分治算法
    ,本篇就帶你較為全面的去認識和了解分治算法。在學習分治算法之前,問你一個問題,相信大家小時候都有存錢罐的經歷,父母親人如果給錢都會往自己的寶藏中存錢,我們每隔一段時間都會清點清點錢。當然這些錢都是想出來的……分治算法介紹分治算法是用了分治思想的一種算法,什麼是分治?
  • 都說算法工程師工資高,你了解什麼是算法嗎?
    1那麼到底什麼是算法呢?廣義上說,算法是就你在解決問題時採用的方法和步驟,其實就是你在編寫程序時,為了實現功能而設計的程序的一步步的流程。2就目前來說,計算機算法主要分為兩大類:一為數值運算算法,一為非數值運算算法。
  • 怎麼製作gif動態表情包?教你把視頻轉gif的方法
    怎麼製作gif動態表情包?表情包作為『第五大發明』受到越來越多人的喜愛,尤其是gif動態表情包在社交中更是必不可少的。那如果你看到一個適合製作動態表情包的視頻時你知道該怎麼去製作嗎?下面分享一個把視頻轉gif的方法。
  • 燃油油位過低警告燈亮了,油箱裡面還有多少油?教你一個簡便算法
    燃油油位過低警告燈亮了,油箱裡面還有多少油?教你一個簡便算法很多車主的提前準備意識不是很強,就拿加油這件事來說吧,很多人總是不記得要及時補充燃油,很固執的等到油量要用完了才去加油站加油,這是一個很不好的習慣。
  • 好用的gif編輯工具我推薦ScreenToGif,小巧方便
    好用的gif編輯工具我推薦ScreenToGif,小巧方便大家好,今天為大家帶來的資源為ScreenToGif這款軟體,對於經常喜歡編輯gif圖片的你或許你聽說過,而對於那些只喜歡看gif圖片的朋友來說可能沒聽過。
  • 程式設計師必須掌握的核心算法有哪些?
    由於我之前一直強調數據結構以及算法學習的重要性,所以就有一些讀者經常問我,數據結構與算法應該要學習到哪個程度呢?,說實話,這個問題我不知道要怎麼回答你,主要取決於你想學習到哪些程度,不過針對這個問題,我稍微總結一下我學過的算法知識點,以及我覺得值得學習的算法。
  • 如果你也用Chrome,你會發現這樣一條警告
    HTTPS 使用非對稱算法交換密鑰,這個也是一個非常精巧的算法,有興趣的同學可以點擊這裡了解下,號稱是20世紀最重要的算法之一。我們來看看這個對話框內容是個什麼鬼。二、如何鑑別你是警察?因為警官證也有可能是假的。
  • 難過到gucci是什麼意思什麼梗 高清gif表情包合集!
    難過到gucci是什麼意思什麼梗 高清gif表情包合集!時間:2018-05-26 21:19   來源:今日頭條   責任編輯:毛青青 川北在線核心提示:原標題:難過到gucci是什麼意思什麼梗 高清gif表情包合集! 難過到gucci這句話是什麼意思?
  • 到底什麼是算法穩定幣?
    而Basis爆紅後,算法穩定幣板塊中快速出現了一系列「仿盤」,已有項目被懷疑開發團隊套現跑路,幣價跌至1美元下方後無人問津。算法穩定幣也呈現出硬幣的兩面,被喝彩和質疑裹挾。火爆表象之下,算法穩定幣能否登堂入室,還需繼續試驗才能得出結果。
  • 我們到底該如何學習《數據結構與算法》
    在網上開始問各種大佬,統一回復的一句話是,你現在學數據結構了嗎?你數據結構咋學的?現在想想真的是留下啦悔恨的眼淚。既然數據結構與算法重要,到底哪個地方重要呢?下面就來說說:2、重要性體現第一:面試面試確實是第一個體現的點,因為你會發現,面試外企的時候他們第一件事就是啥都不問,上來就是幾道算法題。包括國內的字節跳動。
  • gif轉換成視頻的方法
    如果想要將一張gif動態圖片轉換成視頻你會想到什麼法子哩,好吧,下面就是我想到的法子、這個方法需要藉助一下ppt,新建一個ppt文檔,將gif圖片插入到ppt裡面,操作方法跟平常插入JPG/PNG等格式圖片一樣,在上方工具欄上:插入--圖片,選擇將gif轉換成視頻的gif動態圖片