博客 / 詳情

返回

KMP算法

在應用中經常會遇到字符串比較的算法,判斷一個字符串pp是否是另外一個字符串ss的子串。
註明的算法是KMP算法,現在整理如下,參考 宮水三葉 的代碼實現。

// 作者 宮水三葉
// 鏈接 https://leetcode.cn/problems/find-the-index-of-the-first-occurrence-in-a-string/solution/shua-chuan-lc-shuang-bai-po-su-jie-fa-km-tb86/
// KMP 算法
// ss: 原串(string)  pp: 匹配串(pattern)
// 時間複雜度O(m + n)
public int kmp(String ss, String pp) {
    if (pp.isEmpty()){
        return 0;
    }

    // 分別讀取原串和匹配串的長度
    int n = ss.length(), m = pp.length();
    // 原串和匹配串前面都加空格,使其下標從 1 開始
    ss = " " + ss;
    pp = " " + pp;

    char[] s = ss.toCharArray();
    char[] p = pp.toCharArray();

    // 構建 next 數組,數組長度為匹配串的長度(next 數組是和匹配串相關的)
    int[] next = new int[m + 1];
    // 構造過程 i = 2,j = 0 開始,i 小於等於匹配串長度 【構造 i 從 2 開始】
    for (int i = 2, j = 0; i <= m; i++) {
        // 匹配不成功的話,j = next(j)
        while (j > 0 && p[i] != p[j + 1]){
            j = next[j];
        }
        // 匹配成功的話,先讓 j++
        if (p[i] == p[j + 1]){
            j++;
        }
        // 更新 next[i],結束本次循環,i++
        next[i] = j;
    }

    // 匹配過程,i = 1,j = 0 開始,i 小於等於原串長度 【匹配 i 從 1 開始】
    for (int i = 1, j = 0; i <= n; i++) {
        // 匹配不成功 j = next(j)
        while (j > 0 && s[i] != p[j + 1]){
            j = next[j];
        }
        // 匹配成功的話,先讓 j++,結束本次循環後 i++
        if (s[i] == p[j + 1]){
            j++;
        }
        // 整一段匹配成功,直接返回下標
        if (j == m){
            return i - m;
        }
    }

    return -1;
}

如果是java的開發者,可以使用jdk自帶的

// 時間複雜度O(m * n)
ss.indexOf(pp);
user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.