KMP算法之k=next[k]簡要解析

Ax             
AAy
AAAz                                                                                      
AAAAdm 

 

求 next[mi] 。  mi代表m在數組中的index。 zi,yi,xi亦如此。

如圖z和d不相等,則需要比較y和d, 
AAy
AAz
next[zi] = yi = k
y=array[k]

如果y和d相同, 則next[mi] = k+1
如果y和d不相等,則需要比較d和x
Ax
Ay

next[yi] = xi = k1
x=array[k1]

如果x和d相同, 則next[mi]= k1+1
如果x和d不相等,
next[xi] =0


d是否等於array[0]  又回到起點。。。    array[0]  = d 
next[mi] = 1;  

否則 k = next(0) = -1
next[mi] = 0

next[zi] = yi  
next[yi] 是[xi]
next[xi] 是 0
next[0] 是-1   

即d和x,y,z,array[0]都不相等時需要比較m和array[0]的大小。 再次回到起點。哈哈哈

 

可以自行進行驗證:

ab

A=空集。

abacd  

A={a}

Ab

Acd

 

abababcd

A = {ab}

Aa

AAa

AAAcd

 

最基礎的代數法則。

ababababdm

A={ab}

a

Aa

AAa

AAAa

AAAAdm

public  class KMP {
    
    public static void main(String[] args) {
        int index = Solution.kmp("fsdfdasfffsd","ababababdm") ;
        System.out.println(index);
    }

}


class Solution {
    // KMP算法,返回匹配的首字符下標,否則返回-1
    public static int kmp(String s, String t) {
        int m = s.length(), n = t.length();
        int[] next = new int[n];
        getNext(t, next);
        int i = 0, j = 0;
        while (i < m && j < n) {
            if (j == -1 || s.charAt(i) == t.charAt(j)) {
                i++;
                j++;
            } else j = next[j];
        }
        if (j >= n) return i - n;
        else return -1;
    }

    // 計算next數組
    private static void getNext(String t, int[] next) {
        int j = 0, k = -1, n = t.length();
        next[0] = -1;
        while (j < n - 1) {
            if (k == -1 || t.charAt(j) == t.charAt(k)) {
                // System.out.printf("j===%d,k===%d%n",j,k);
                j++;
                k++;
                next[j] = k;
            } else {
                System.out.printf("j===%d,k===%d%n",j,k);
                k = next[k];
            }
        }
    }
}

 

在這裏能發現一個很有意思的事情,當j相同時,k的排列爲一個等差數列,步長爲A的長度。

kmp算法適用於p串有重複字串的場景,當p串沒有重複的字串時和暴力解法一樣。

改進版的KMP算法。

public class KMP {

    public static void main(String[] args) {
        int index = Solution.kmp("fsdfdasfffsd", "abcabdabcabababababababababdm");
        System.out.println(index);
    }

}


class Solution {
    // KMP算法,返回匹配的首字符下標,否則返回-1
    public static int kmp(String s, String t) {
        int m = s.length(), n = t.length();
        int[] next = new int[n];
        getNext(t, next);
        int i = 0, j = 0;
        while (i < m && j < n) {
            if (j == -1 || s.charAt(i) == t.charAt(j)) {
                i++;
                j++;
            } else {
                j = next[j];
            }
        }
        if (j >= n) {
            return i - n;
        } else {
            return -1;
        }
    }

    // 計算next數組
    private static void getNext(String t, int[] next) {
        int j = 0, k = -1, n = t.length();
        next[0] = -1;
        while (j < n - 1) {
            if (k == -1 || t.charAt(j) == t.charAt(k)) {
                // System.out.printf("j===%d,k===%d%n",j,k);
                j++;
                k++;

                if (t.charAt(j) == t.charAt(k)) {  // 當兩個字符相等時要跳過
                    next[j] = next[k];
                } else {
                    next[j] = k;
                }

            } else {
                System.out.printf("j===%d,k===%d%n", j, k);
                k = next[k];
            }
        }
    }
}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章