《數據結構》學習筆記3——串匹配
/*.. 前言:感謝學堂在線的學習資源!!!感謝鄧公!!本文代碼均整理自課件 ..*/
通常,字符種類不多,而串長>>字符種類數量。
% grep <pattern> <text> 定義:模式P 文本T
Pattern matching: detection? location? counting? enumeration?(本文主要討論出現位置)
數據結構,借助C++中<cstring>頭文件:
詳情參考 http://www.cplusplus.com/reference/cstring/ http://www.cplusplus.com/reference/string/string/
算法性能評估:隨機T,對成功、失敗的匹配分別測試(成功,在T中,隨機取出長度為m的子串作為P,分析平均復雜度;失敗,采用隨機P,統計平均復雜度)
蠻力算法:O(m*n)
1 int match_BruteForce(char * P, char * T) { 2 size_t n = strlen(T), i = 0; 3 size_t m = strlen(P), j = 0; 4 for (i = 0; i <= n - m; ++i) { 5 for (j = 0; j < m; ++j) 6 if (T[i + j] != P[j]) breakint match_BruteForce(char * P, char * T); 7 if (m <= j) break; // 找到匹配子串 8 } 9 return (i > n - m ) ? -1 : i; // 返回-1表示匹配失敗。 10 }
KMP算法(Kunth Morris Pratt三位大家):O(m+n)
相比蠻力算法優化:P快速右移,避免重復比對(利用成功匹配的經驗,構造next表)。
【下圖1體會KMP比對過程,優化前的next表】【圖2 next表構造思路】【圖3自繪優化後的next表構造程序流程圖,啊哈哈哈】
當使用蠻力算法,單次匹配概率越小時(比如P中為較少出現的字符),此時最好情況接近O(n),KMP相比蠻力算法優勢不明顯。而例如二進制串匹配,則KMP算法性能優勢明顯。
1 int match_KMP(char * P, char * T) { 2 int * next = buildNext(P); 3 int n = (int)strlen(T), i = 0; 4 int m = (int)strlen(P), j = 0; 5 while (j < m && i < n) 6 if (j < 0 || T[i] == P[j]) { // 匹配 7 i++; j++; 8 } 9 else // 失敗 10 j = next[j]; 11 delete[] next; 12 // return i - j; // 返回 13 return (i - j > n - m) ? -1 : i; // 返回-1表示匹配失敗。 14 }int match_KMP(char * P, char * T)
BM_BC算法 [ Boyer + Moore, 1997] :最好O(n/m),最差O(n*m) (壞字符 Bad Character – 失敗教訓)
相比KMP算法,由於越靠後的位置,作用越大,因此對模式串P從後向前匹配。(利用匹配失敗的經驗)
構建bc表:記錄全字符在匹配串中的位置,在匹配失敗時【右】移動至匹配的位置,使得當前匹配成功。
優點:單次匹配概率越小時,性能優勢越明顯(大字母表,特別是Unicode);P越長,移動效果越明顯。
缺點:單次匹配概率越大的場合,性能越接近蠻力算法(小字母表,DNA)。
1 int * buildBC(char * P) { 2 int * bc = new int[256]; //bc表,與字母表等長 3 for (size_t j = 0; j < 256; ++j) bc[j] = -1; // 此初始化可省略 4 for (size_t m = strlen(P), j = 0; j < m; j++) 5 bc[P[j]] = j; //不斷覆蓋P[j]的出現位置 6 return bc; 7 }int * buildBC(char * P)
BM_GS算法 :兼顧BM_BC算法和KMP算法的思路(好後綴 Good Suffix – 成功經驗)
【下圖體會一下同時考慮匹配好後綴,和壞字符的策略】
性能比較:BM_GS算法最壞O(n/m),最好O(m+n)
Karp-Rabin 算法:串即是數!(這是一種思想!)
算法:散列+ 相鄰串的位運算O(1)
利用散列(模余函數)對串進行篩選,再進一步確認是否匹配;每一次篩選,即從上一個串的散列值到下一個串的散列值,計算只需要O(1)時間。
《數據結構》學習筆記3——串匹配