KMP算法的時間復雜度與next數組分析


一、什么是 KMP 算法

KMP 算法是一種改進的字符串匹配算法,用於判斷一個字符串是否是另一個字符串的子串

 

二、KMP 算法的時間復雜度

O(m+n)

 

三、Next 數組 - KMP 算法的核心

KMP算法的核心是利用匹配失敗后的信息,盡量減少模式串與主串的匹配次數以達到快速匹配的目的。具體實現就是通過一個 next() 實現

1、next 數組

長度與字符串長度一致,每個位置存儲對應字符的最長匹配長度

 

2、next 數組通過遍歷子字符串中"前綴"和"后綴"的最長的共有元素的長度來獲得

例如 ABCDABD,得到的 next 數組為 [0,0,0,0,1,2,0]

簡單地觀察一下就會發現,該算法會進行最少 21 次的字符串判斷,這還是在不考慮字符串匹配的時間消耗,光此一項的時間復雜度就是

O(n) = (n(n - 1)) /2 = n² / 2 + n / 2 = n²

在加上匹配字符串,就是m + n²顯然大於KMP算法的時間復雜度m + n

3、next數組通過加入回溯法,在遍歷子字符串時,判斷逐步判斷字符是否相同

function get_next(s) {
    var i = 1;
    var j = 0;
    var next = [0];
    while (i < s.length) {
        if (j == 0 || s.charAt(i - 1) == s.charAt(j - 1)) {
            i++;
            j++;
            next.push(j);
        } else {
            j = next[j - 1];
        }
    }
    return next;
}

例如:

j=0,    i=1,    (j=0),     next=[0,1];
j=1,    i=2,    (A!=B),    j=next[0];
j=0,    i=2,    (j=0),    next=[0,1,1];
j=1,    i=3,    (A!=C),    j=next[0];
j=0,    i=3,    (j=0),    next=[0,1,1,1];
j=1,    i=4,    (A!=D),    j=next[0];
j=0,    i=4,    (j=0),    next=[0,1,1,1,1];
j=1,    i=5,    (A=A),    next=[0,1,1,1,1,2];
j=2,    i=6,    (B=B),    next=[0,1,1,1,1,2,3];

總共運行9次就獲得了next數組,算法時間復雜度是O(n) = n

4、對於兩個next數組的用法也有區別

//1.阮
//i值即移動位數:移動位數 = 已匹配的字符數 - 對應的部分匹配值
function kmp(s1, s2) {
    var next = getNext(s2);
    var j = 0;
    for (var i = 0; i < s1.length;) {
        for (; j < s2.length; j++) {
            if (s1.charAt(i + j) != s2.charAt(j)) {
                i += j > 0 ? (j - next[j - 1]) : 1;
                j = next[j > 0 ? j - 1 : 0];
                break;
            } else if (j == s2.length - 1) {
                return i;
            }
        }
    }
    return -1;
}
 
//2.程
function kmp2(s1, s2) {
    var j = 0;
    var next = get_next(s2);
    for (var i = 0; i < s1.length;) {
        for (; j < s2.length; j++) {
            if (s1.charAt(i) != s2.charAt(j)) {
                j == 0 ? i++ : true;
                j = next[j > 0 ? j - 1 : 0];
                break;
            } else if (j == s2.length - 1) {
                return i - j;
            }
            i++;
        }
    }
    return -1;
}
 
//3.也正是由於i值的大小隨着j值的大小進行改變,
//  使得被查找字符串僅被遍歷一次即可得到解。
//  故時間復雜度為m
//  加上獲得next數組的時間復雜度就是kmp算法的總時間復雜度m+n;

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM