KMP 算法 筆記

KMP 包含一個PMT表。

我們把 待匹配的文字稱爲 模式字符串.

前綴 : “aba” 前綴爲 除去 最後一個 字符 “a” 所 形成 的集合。 {“a”,“ab”}
後綴 : “aba” 後綴 爲 除去 最前的一個字符串 “a” 所形成的集合 {“a”,“ba”}

它們 之間的 交集爲 {“a”} ,長度爲 1,那麼 在 PMT表 中 a 對應 1.
在這裏插入圖片描述

模式字符串 issip 在 某一個 地方 出現 不匹配,那麼 至少 在 前 j -1 個字符是匹配的.
在這裏插入圖片描述
如果 是普通的 做法,如果我們 碰到 不匹配的 字符就把 j 指針置 爲 0,這樣就錯過了 可能能匹配的字符串,

之所以發生這樣的情況 是因爲 受到 上一次匹配的影響,而導致 錯過了 。

在 上上張圖中 ,假設 我們 錯過了 匹配 隱含的意思是,在 前 j -1 個數中,和 i - j 個數中 ,必然 會存在 公共的部分。

對吧 要匹配 那麼 最基本的 前 n 個數 要一樣吧 。

比如 a 和 ab 能匹配是因爲 都是 以 a 開頭的,那麼 我們 就可以 證明 像 abc 不可能 出現上面錯過的情況,爲什麼呢?
假設 有個字符串 m 和你匹配 , 前幾個 都一樣 但是唯獨 c 不一樣,那麼 你想想 如果 出現上面 那種情況的話 一位 這 在已匹配的 ab 裏面 還要 有一個 a ,因爲 匹配 是以 a 開頭的。如果 你因爲 匹配 abc 而錯過了 可能成功匹配的字符,那麼 必然 在 匹配ab 的時候 還有一個 a 對應。
說的簡單點 就是 你要匹配一個字符串 至少 開頭 要一樣吧,那麼 如果 一個沒有一個重複數字的字符串。 你怎麼 可能再次 匹配到呢?
在這裏插入圖片描述

那麼我們再 舉個例子 “aba” 注意到 沒有 這個 字符串 a 出現了 兩次 。

舉個例子 :
abc
ababc

在這裏插入圖片描述當我們 的 a 和 c 作比較的時候 不相等,但是 匹配字符串 是以 a 開頭的 那麼 我們不希望 錯過可能的 下一次匹配機遇,那我們 就 嘗試 把 j 的索引 改成 0 再次開始 匹配。

再 舉個例子:
在這裏插入圖片描述

a b a 集合
前綴 {a,ab}
後綴 {ba,a}
交集 {a}

在這裏插入圖片描述

在 j = 3 ,出現不匹配 ,而且 a 出現了 2次 那麼 那麼第二次a出現的位置 正好可以 當做 另一次 匹配的 開始。

在這裏插入圖片描述

前面 aba 的 前後綴的交集 把 a 我們可以把 a 看做一個模式
那麼 abab 的 前後綴的交集 ab 就是一個模式

在這裏插入圖片描述
next 就是 pmt 表 前面 第0 爲 push -1 然後 最後一位 remove。

計算 pmt 表 rust 代碼

pub fn pmt(needle: String) ->Vec<usize>{
    let mut tmpvec = Vec::with_capacity(needle.len());
    tmpvec.push(0);
    let mut j = 0;
    let mut i = 1;
    for _ in 1.. needle.len() {
        if needle.as_bytes()[i] != needle.as_bytes()[j] {
            while needle.as_bytes()[i] != needle.as_bytes()[j] && j >= 1 {
                    j = tmpvec[j-1];
            }
        }
        if needle.as_bytes()[i] == needle.as_bytes()[j]{
            j += 1;
        }
        tmpvec.push(j);
        i +=1;
    }
   tmpvec
}

完整算法:https://qiaojinxia.github.io/chapter_7.html

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