大廠程式設計師必備十大基礎演算法 KMP演算法

2021-10-05 02:44:33 字數 3007 閱讀 3219

字串匹配問題:

有乙個字串 str1= 「010101010101010010101010101」,和乙個子串 str2=「0101010100」

現在要判斷 str1 是否含有 str2, 如果存在,就返回第一次出現的位置, 如果沒有,則返回-1

如果用暴力匹配的思路,並假設現在 str1 匹配到 i 位置,子串 str2 匹配到 j 位置,則有:

如果當前字元匹配成功(即 str1[i] == str2[j]),則 i++,j++,繼續匹配下乙個字元

如果失配(即 str1[i]! = str2[j]),令 i = i - (j - 1),j = 0。相當於每次匹配失敗時,i 回溯,j 被置為 0。

用暴力方法解決的話就會有大量的回溯,每次只移動一位,若是不匹配,移動到下一位接著判斷,浪費了大量的時間。(不可行!)

暴力匹配演算法實現.

暴力匹配的**實現:

public class violencematch 

public static int violencematch(string str1,string str2)else

} //判斷是否匹配成功

if(j == s2len)else

}}

kmp 是乙個解決模式串在文字串是否出現過,如果出現過,最早出現的位置的經典演算法。

knuth-morris-pratt 字串查詢演算法,簡稱為 「kmp 演算法」,常用於在乙個文字串 s 內查詢乙個模式串 p 的出現位置,這個演算法由 donald knuth、vaughan pratt、james h. morris 三人於 1977 年聯合發表,故取這 3 人的姓氏命名此演算法。

kmp 方法演算法就利用之前判斷過資訊,通過乙個 next 陣列,儲存模式串中前後最長公共子串行的長度,每次回溯時,通過 next 陣列找到,前面匹配過的位置,省去了大量的計算時間。

字串匹配問題:

有乙個字串 str1= 「bbc abcdab abcdabcdabde」,和乙個子串 str2=「abcdabd」

現在要判斷 str1 是否含有 str2, 如果存在,就返回第一次出現的位置, 如果沒有,則返回-1

要求:使用 kmp 演算法完成判斷,不能使用簡單的暴力匹配演算法.

思路分析:

舉例來說,有乙個字串 str1 = 「bbc abcdab abcdabcdabde」,判斷,裡面是否包含另乙個字串 str2 =「abcdabd」?

重複第一步,還是不符合,再後移

一直重複,直到str1有乙個字元與str2的第乙個字元符合為止

接著比較字串和搜尋詞的下乙個字元,還是符合。

遇到 str1 有乙個字元與 str2 對應的字元不符合。

怎麼做到把剛剛重複的步驟省略掉?可以對 str2 計算出一張《部分匹配表》,這張表的產生在後面介紹

已知空格與d不匹配時,前面六個字元」abcdab」是匹配的。查表可知,最後乙個匹配字元b對應的」部分匹配值」為2,因此按照下面的公式算出向後移動的位數: 移動位數 = 已匹配的字元數 - 對應的部分匹配值 因為 6 - 2 等於4,所以將搜尋詞向後移動 4 位。

因為空格與 a 不匹配,繼續後移一位。

逐位比較,直到發現 c 與 d 不匹配。於是,移動位數 = 6 - 2,繼續將搜尋詞向後移動 4 位。

介紹《部分匹配表》怎麼產生的。先介紹字首,字尾是什麼

「部分匹配值」就是」字首」和」字尾」的最長的共有元素的長度。以」abcdabd」為例,

」部分匹配」的實質是,有時候,字串頭部和尾部會有重複。比如,」abcdab」之中有兩個」ab」,那麼它的」部分匹配值」就是 2(」ab」的長度)。搜尋詞移動的時候,第乙個」ab」向後移動 4 位(字串長度- 部分匹配值),就可以來到第二個」ab」的位置。

到此 kmp 演算法思想分析完畢!

kmp演算法的**實現如下:

public class kmpalgorithm 

//獲取到乙個字串(子串)的部分匹配值表

public static int kmpnext(string dest)

if(dest.charat(i) == dest.charat(j))

next[i] = j;

} return next;

} /**

* * @param str1 源字串

* @param str2 子串

* @param next 子串的部分匹配表

* @return -1沒有匹配到,否則返回第乙個匹配到位置

*/public static int kmpsearch(string str1,string str2,int next)

if(str1.charat(i) == str2.charat(j))

if(j == str2.length())

} return -1;

}

}

程式設計師必備十大演算法3 歸併排序

十大演算法之歸併排序首先要有分治的思想 歸併排序的過程 1 建立歸併函式入口mergesort a,n a是陣列a,n為陣列長度 入口中要有乙個動態分配陣列,長度為n int malloc nsizeof int 2 建立乙個msort函式msort a,arr,0,n 1 用來做二分0和n 1就是...

程式設計師必備十大演算法 最短路徑(1)

最短路徑的演算法大致可以分為三種,不過每一種的演算法都有所不同 在時間複雜度 空間複雜度 負權 有負權的邊 是否可以檢驗有沒有負權或者帶負權的邊 這個演算法比較簡單,暴力解決,時間複雜度為pow n,3 空間複雜度為pow n,2 可以處理負權和帶負權邊的演算法 最短路徑 1 include usi...

程式設計師必備十大演算法 貪心演算法1 找錢問題

貪心演算法比較侷限,因為在決策上存在分歧,還有待證明,但是和動態規劃的思想一樣,都是從區域性最優解到整體最優解 今天講一下貪心演算法可以解決的其中乙個問題 找錢問題 首先說說一下思路,也就是核心演算法 找錢的規則是盡可能少的紙幣數找齊,找不齊就說 找不齊 找齊就輸出找錢的方法和紙幣張數,每張紙幣的張...