字符串匹配(KMP)算法及Java實現

1、什麼是KMP算法?java


   維基百科的解釋是:在計算機科學中,Knuth-Morris-Pratt字符串查找算法(簡稱爲KMP算法)可在一個主文本字符串S內查找一個詞W的出現位置。此算法經過運用對這個詞在不匹配時自己就包含足夠的信息來肯定下一個匹配將在哪裏開始,從而避免從新檢查先前已經匹配過的字符。算法


2、字符串的前綴與後綴數組


     前綴:字符串除了最後一個字符的所有頭部組合;ide

     後綴:字符串處理第一個字符的所有頭部組合;例如spa

圖片.png

3、字符串部分匹配表圖片


        "部分匹配"的實質是,有時候,字符串頭部和尾部會有重複。好比,"ABCDAB"之中有兩個"AB",那麼它的"部分匹配值"就是2("AB"的長度)。搜索詞移動的時候,第一個"AB"向後移動4位(字符串長度-部分匹配值),就能夠來到第二個"AB"的位置。因此咱們須要找到一個字符串中每個子串的匹配值,即找到字符串的部分匹配值表,這樣的話咱們在下面匹配字符串的過程當中就能夠根據匹配表來進行跳躍了,而沒必要一個一個字符日後移,這就是關鍵所在。字符串

圖片.png

4、KMP算法實現過程get


      簡單來講,KMP算法就是根據上面咱們已經獲得的部分匹配表來判斷:匹配過程當中發現子串的某個字符與待匹配串不對應時,子串應該日後移幾位。字符串處理

移動的位數 = 已經匹配成功的串的總長度 - 已經匹配成功的串的部分匹配值 it

     有些繞,舉個栗子,假如我要判斷字符串"BBC ABCDAB ABCDABCDABDE"中是否含有串「ABCDABD」,我把前面這個長串叫作待匹配串,把「ABCDABD」叫作子串(有可能叫法不對但明白就行)。

匹配的過程爲:


    將字符串"BBC ABCDAB ABCDABCDABDE"的第一個字符與搜索詞"ABCDABD"的第一個字符,進行比較。由於B與A不匹配,因此搜索詞後移一位。直到有匹配的字符位置,以下:


圖片.png

圖中當匹配到D時發現不對應了,此時:

已經匹配成功的串爲:ABCDAB

已經匹配成功的串的總長度:6

已經匹配成功的串的部分匹配值 :2

移動的位數 = 6 - 2,直接將子串日後移動4位,繼續開始匹配

圖片.png

同樣的道理,此時已經匹配成功的串爲AB,移動的位數 = 2 - 0,日後移動2位繼續匹配


圖片.png



沒有匹配成功的串,日後移一位

圖片.png

已經匹配成功的串爲:ABCDAB,ABCDAB的部分匹配值爲2,移動的位數 = 6 - 2,日後移動4位

   圖片.png

此時子串全部的字符都被匹配,搜索完成。


5、Java實現

public class KmpAlgo {
    //尋找待匹配串的部分匹配值,放在next數組中
    static void getNext(String pattern,int[] next){
        int j = 0;
        int k = -1;
        next[0] = -1;
        int len = pattern.length();
        while(j < len-1){
            if(k == -1 || pattern.charAt(j) == pattern.charAt(j)){
                j++;
                k++;
                next[j] = k;
            }else{
                k = next[k];
            }
        }
        
    }
    
    static int kmp(String s,String pattern){
        int i = 0;
        int j = 0;
        int slen = s.length();
        int plen = pattern.length();
        int[] next = new int[plen];
        getNext(pattern,next);
        while(i < slen && j < plen){
            if(s.charAt(i) == pattern.charAt(j)){
                i++;
                j++;
                
            }else if(next[j] == -1){
                i++;
                j = 0;
            }else{
                j = next[j];
            }
            if(j == plen){
                return i-j;
            }
        }
        return -1;
        
    }
    /**
     *@param
     */
    public static void main(String[] args){
        String str = "ABCDABDEYGF";
        String pat = "ABCDABD";
        //KmpAlgo.kmp(str, pat);
        System.out.println(KmpAlgo.kmp(str, pat));
    }

}
相關文章
相關標籤/搜索