一.基本概念:
真字首指的是除了本身以外字串全部頭部的組合,真字尾指的是除了本身以外字串全部尾部的組合。
二.簡單的模式匹配演算法
按照正常的思維,字串可以進行暴力匹配,**如下。
int index_bf(string s,string p)
else
} if(j == p_len)
else
return -1;
}
暴力匹配的時間複雜度為o(mn),在處理大字串很難滿足我們的需求。
因此接下來介紹kmp演算法,時間複雜度為o(m+n)。
三.kmp演算法
3.1演算法流程
摘自部落格
(1)首先,主串"bbc abcdab abcdabcdabde"的第乙個字元與模式串"abcdabd"的第乙個字元,進行比較。因為b與a不匹配,所以模式串後移一位。
(2)因為b與a又不匹配,模式串再往後移。
(3)就這樣,直到主串有乙個字元,與模式串的第乙個字元相同為止。
(4)接著比較主串和模式串的下乙個字元,還是相同。
(5)直到主串有乙個字元,與模式串對應的字元不相同為止。
(6)這時,最自然的反應是,將模式串整個後移一位,再從頭逐個比較。這樣做雖然可行,但是效率很差,因為你要把"搜尋位置"移到已經比較過的位置,重比一遍。
(7)(8)i01
2345
67模式串abc
dabd
'\0'
next[i]-10
0001
20怎麼做到這一點呢?可以針對模式串,設定乙個跳轉陣列int next
,這個陣列是怎麼計算出來的,後面再介紹,這裡只要會用就可以了。
(9)已知空格與d不匹配時,前面六個字元"abcdab"是匹配的。根據跳轉陣列可知,不匹配處d的next值為2,因此接下來從模式串下標為2的位置開始匹配。
(10)
因為空格與c不匹配,c處的next值為0,因此接下來模式串從下標為0處開始匹配。
(11)
因為空格與a不匹配,此處next值為-1,表示模式串的第乙個字元就不匹配,那麼直接往後移一位。
(12)
逐位比較,直到發現c與d不匹配。於是,下一步從下標為2的地方開始匹配。
(13)
逐位比較,直到模式串的最後一位,發現完全匹配,於是搜尋完成。
3.2獲得next陣列
//得到next陣列
void getnext(string p,int next)
else
}}
3.3kmp完整**
#include #include#includeusing namespace std;
const int n = 1005;
//得到next陣列
void getnext(string p,int next)
else }}
int kmp(string s,string p,int next)
else
} if(j == p_len)
else
}int main();
cout最後限於本人今天還有一丟丟事情沒做,以及kmp優化演算法的一些些的小缺陷,就先寫到這。
參考:
模式匹配 KMP演算法
字串匹配演算法 include includeusing namespace std define ok 1 define error 0 define overflow 2 typedef int status define maxstrlen 255 使用者可在255以內定義最長串長 typed...
模式匹配KMP演算法
前些日子在為目前該學習什麼而苦惱,就問了一下已經從事多年軟體開發的表哥,他說乙個程式設計師要走的遠,就要學好資料結構和演算法,於是我就重新開始學習資料結構和演算法了 拿起以前上過的資料結構看,看到第四章串的模式匹配時,頗感興趣,就寫了一下程式,實踐了一下。感覺還蠻爽,於是就把以下幾個重要的函式放在此...
KMP模式匹配演算法
首先,這是由knuth morris和prattle三人設計的線性時間字串匹配演算法。這裡就不仔細的講解,網上有更好的講解,在這推薦幾個自己當時學習的kmp所看到的較好理解的 這裡附上自己所學的 includeusing namespace std s 是主串 p 是模式串 int next 100...