網易等公司在筆試中經常會考察有關字串的題目,因此,我們要掌握相關演算法。通常這些題目會考察模式匹配,以及情況的列舉,因此,本文介紹經典的kmp模式匹配演算法和經典的全排列演算法。下面首先介紹字串相關知識。
假定有字串s1,s2,strcpy(s1,s2)表示將s2賦值給s1;strcat(s1,s2)表示將s2連線到s1後面;strchr(s,c)從串s中查詢字元c;strcmp(s1,s2)比較s1,s2,s1=s2返回0,s1s2返回1;strlength(s)表示s的長度。
對於s1和s2的比較,舉個例子:s1=abc,s2=abcd,則s2>s1;s1=abc,s2=abb123,則s1>s2。
模式匹配:對於主串s和子串t,在s中尋找t的過程稱為模式匹配,找到返回t在s中的位置,否則返回0。
對於模式匹配,樸素的演算法使bf演算法,思想很簡單,就是子串對主串迴圈遍歷比較,但是這種方法有大量的重複比較,效率很低,kmp演算法是對bf演算法的改進。kmp演算法的思想是對主串s和子串(模式)t進行模式匹配,主串中的字元只匹配一次。那麼如何實現呢?如下圖所示,子串t和主串s匹配,si和tj不匹配,將子串t向右移動k個單位,tk繼續和si比較。
那麼,這個k值是如何來的呢?為了讓主串每個字元只匹配一次,kmp演算法對子串進行了分析,k值只與子串有關。一般確定k值的函式為next函式。next陣列的含義就是每個子串的最長字首與最長字尾的相同長度。假設我們的子串為ababaca,那麼我們對其進行分析。ababaca,長度是7,所以next[0],next[1],next[2],next[3],next[4],next[5],next[6]分別計算的是 a,ab,aba,abab,ababa,ababac,ababaca的相同的最長字首和最長字尾的長度。它們的相同的最長字首和最長字尾分別是0,0,a,ab,aba,0,a。(注意,最長字首不包括最後乙個字元) 所以next陣列的值是[0,0,1,2,3,0,1]。
現在大家該明白為何只需移動k個單位,子串就可以繼續與主串匹配了吧,如上圖所示,子串的3,4區域是相等的,即字首等於字尾,所以只要子串向右移動k個單位,相等的字首與字尾重合,無需比較,只要接著匹配tk與si即可。以上就是kmp演算法的乙個難點。還有乙個關鍵是next函式的實現,這也是一大難點。實際上弄懂了next,就弄懂了kmp演算法。
**如下:
在calc_next函式中,我們拿相同的前字尾那一部分比較,k表示相同的最大字首與最大字尾長度,如果t[k+1]==t[j],那麼k++,next[j]=k,如果不相等,令k=next[k],k=next[k]是理解的難點。當t[k+1]!=t[j],我們就要對t[j]前的長度為k的字尾進行分析,看那個字尾是否有相同前字尾,如下圖:
kmp演算法原理如下圖:
KMP演算法經典講解
kmp演算法的思想都是一樣的,看了很多講解,基本上都只是在next陣列的表示上是有區別的,我覺得乙個很6的大神,講的很好 這位大神的next i 表示的是如果模板串p的第i位與母串s匹配失敗,則從模板串的哪個位置開始進行下一次比較。母串s和模板串p都是從0開始到len 1,next陣列也是從0開始,...
白話經典演算法系列
堆排序與快速排序,歸併排序一樣都是時間複雜度為o n logn 的幾種常見排序方法。學習堆排序前,先講解下什麼是資料結構中的二叉堆。二叉堆的定義二叉堆是完全二叉樹或者是近似完全二叉樹。二叉堆滿足二個特性 1 父結點的鍵值總是大於或等於 小於或等於 任何乙個子節點的鍵值。2 每個結點的左子樹和右子樹都...
演算法 經典演算法
1 匹配演算法 匹配開始,從長的字串開始,匹配成功,長的和短的字串均向後匹配,而匹配失敗,則長的字串從開始的位置向後乙個字元,重新開始匹配,而短的字串則完全從頭開始。匹配演算法 param str1 長匹配字串 param str2 短的匹配字串 return 匹配成功 返回短字串在長字串開始的位置...