字串匹配怎麼能少了大名鼎鼎的kmp演算法呢?
概念:好字首:直到遇到壞字元為止,最長的字首子串。
好字首的所有字尾子串中,最長的可匹配字首子串的那個字尾子串,叫作最長可匹配字尾子串;對應的字首子串,叫作最長可匹配字首子串
直接上思路:
1.kmp演算法和bm演算法完全相反,kmp演算法採用從前到後進行比較。
2.kmp演算法主要是為了找:最長可匹配字尾子串(最長可匹配字首子串)。
3.kmp 演算法也可以提前構建乙個陣列,用來儲存模式串中每個字首(這些字首都有可能是好字首)的最長可匹配字首子串的結尾字元下標。我們把這個陣列定義為 next 陣列。做預處理操作時,不需要主串,只需要模式串。
4.有了 next 陣列,我們很容易就可以實現 kmp 演算法了。
直接上**:
// a, b分別是主串和模式串;n, m分別是主串和模式串的長度。
public static int kmp(char a, int n, char b, int m)
if (a[i] == b[j])
if (j == m)
} return -1;
}
下面到了最難的部分,構建next陣列思路如下:
1.如果 next[i-1]=k-1,也就是說,子串 b[0, k-1]是 b[0, i-1]的最長可匹配字首子串。如果子串 b[0, k-1]的下乙個字元 b[k],與 b[0, i-1]的下乙個字元 b[i]匹配,那子串 b[0, k]就是 b[0, i]的最長可匹配字首子串。所以,next[i]等於 k。
2.既然 b[0, i-1]最長可匹配字尾子串對應的模式串的字首子串的下乙個字元並不等於 b[i],那麼我們就可以考察 b[0, i-1]的次長可匹配字尾子串 b[x, i-1]對應的可匹配字首子串 b[0, i-1-x]的下乙個字元 b[i-x]是否等於 b[i]。如果等於,那 b[x, i]就是 b[0, i]的最長可匹配字尾子串。
可是,如何求得 b[0, i-1]的次長可匹配字尾子串呢?次長可匹配字尾子串肯定被包含在最長可匹配字尾子串中,而最長可匹配字尾子串又對應最長可匹配字首子串 b[0, y](兩個完全一樣,次長可匹配字首子串和次長可匹配字尾字串也完全相同)。於是,查詢 b[0, i-1]的次長可匹配字尾子串,這個問題就變成,查詢 b[0, y]的最長匹配字尾子串的問題了。
3.按照這個思路,我們可以考察完所有的 b[0, i-1]的可匹配字尾子串 b[y, i-1],直到找到乙個可匹配的字尾子串,它對應的字首子串的下乙個字元等於 b[i],那這個 b[y, i]就是 b[0, i]的最長可匹配字尾子串。
最後,上**:
// b表示模式串,m表示模式串的長度
private static int getnexts(char b, int m)
if (b[k + 1] == b[i])
next[i] = k;
} return next;
}
完結! 認真背演算法day03
昨天高強度背了bm演算法和kmp演算法,今天整點陽間的休閒一下。今天主要講兩個東西,乙個是堆排序,乙個是圖的深度遍歷 回溯演算法 和廣度遍歷。堆排序為什麼堆這麼重要呢?因為堆是可以用陣列表示的,假設堆上某個節點在陣列中下標為i,則其左右孩子節點的下標為i 2和i 2 1。下面講解堆排序的思路 我看過...
認真背演算法day04
好久沒更新演算法了,今天再更新一天。今天主要複習一下trie樹和ac自動機 1.trie樹 trie 樹,是一種專門處理字串匹配的資料結構,用來解決在一組字串集合中快速查詢某個字串的問題。trie樹的記錄方法 每乙個節點,都記錄其所有可能出現的字元,以乙個陣列形式組織,陣列中存放節點。具體組織形式如...
day02 常用演算法 排序
氣泡排序 思路 相鄰的兩個數進行比較,會進行n 1輪比較,每一輪會比較n 1次之後,將陣列中最大的數排在最後 注意 每一次比較之後會交換變數值 package homework public class a02 for int i 0 i nums.length 1 i for int i 0 i ...