模式匹配是資料結構中字串的一種基本運算。
由於字串我們學習過了,大部分操作都比較清楚,但是模式匹配相對來說操作稍微有些難度,所以我們在這裡簡單的進行講述。
模式匹配的具體操作如下:給定乙個子串(也稱為模式串),要求在某個字串中找出與該子串相同的所有子串。
我們在此講述2種常見實現:
暴力匹配
kmp演算法
主要思想:從主串的第乙個元素開始,與模式串第乙個元素相比較,相等則逐一比較,若有不同元素,主串回溯至下乙個元素,與模式串的乙個元素相比較,依次迴圈。
為了方便講解,我們針對下面的案例來進行講解:
要求在尋找模式串第一次在主串出現的位置,未找到則返回-1。
我們把這個過程分為5步:
首先,我們需要將主串進行遍歷。
主串的每一次遍歷中,與模式串進行比較,若相同比較下乙個元素。
如果模式串比較結束,說明模式串成功匹配,返回主串當前下標。
如果兩元素不同,說明此處匹配失敗,主串繼續遍歷下乙個元素。
若主串遍歷結束,仍未成功匹配,則說明主串中無該模式串,返回-1。
我們舉個例子演示一下,假設主串abdabcda,模式串abcd,模式匹配後應當得到3。
主串當前遍歷到的元素/下標
主串的元素
模式串元素
比較a/0aa
相等,比較下乙個元素
a/0b
b相等,比較下乙個元素
a/0d
c不相等,回溯,繼續遍歷主串
b/1b
a不相等,回溯,繼續遍歷主串
d/2d
a不相等,回溯,繼續遍歷主串
a/3a
a相等,比較下乙個元素
a/3b
b相等,比較下乙個元素
a/3c
c相等,比較下乙個元素
a/3d
d相等,比較下乙個元素
a/3a
\0模式串比較結束,匹配成功
public
static
intbruteforcestringmatch
(string str, string pattern)
else
}//模式串匹配結束,表示匹配成功
if(loopofpattern == pattern.
length()
)}//模式匹配失敗
return-1
;}
時間複雜度設主串和模式串的長度分別為m,n,則它在最壞情況下的時間複雜度是o(m*n)。
kmp演算法
主要解決了bf演算法的回溯問題,從而降低了時間複雜度。他的時間複雜度為o(m+n)。
主要思想:kmp演算法的關鍵是利用匹配失敗後的資訊, 盡量減小兩串的匹配次數,以達到快速匹配的目的。通過乙個next陣列尋找最長且相同的字首和字尾,以減少匹配次數。
我們舉個例子,來看看kmp演算法是怎麼工作的
主串:aaaaab
模式串:aaab
bf演算法求解時:
我們在匹配時會發現,第一次中模式串與主串只有第四個元素不相同,其他元素相同。同時我們發現,模式串中前3個元素是相同的,我們不妨想想,第二次匹配時,模式串的前兩個字母還有必要去比較嗎?
顯然這兩次的比較是沒有必要的,那麼我們就要借助next陣列來幫忙了。
模式串aaab的next陣列值為,我們在後面會講解next陣列如何求取。我們在第一次匹配時,第四個元素不同,模式串下標移至next[3]的位置,即2,也就是下一次從第三個a的位置開始匹配,直接跳過了前兩個a,減少了匹配時比較次數。之後是類似的操作。
我們將kmp演算法匹配的過程也分為5步:
首先,我們需要將主串進行遍歷。
主串的每一次遍歷中,與模式串進行比較,若相同比較下乙個元素。
如果模式串比較結束,說明模式串成功匹配,返回主串當前下標。
如果兩元素不同,說明此處匹配失敗,模式串下標更新至next值的位置,主串繼續遍歷下乙個元素。
若主串遍歷結束,仍未成功匹配,則說明主串中無該模式串,返回-1。:
kmp演算法求解時:
}//模式串匹配結束,表示匹配成功
if(loopofpattern == pattern.
length()
)}//模式匹配失敗
return-1
;}next[ ]陣列
經過上面的例子我們發現,next陣列的求取,是kmp演算法的最重要的一環,那麼next陣列究竟應該怎麼求呢?
next陣列實際上儲存了模式串每乙個元素的字首與字尾相同的最大長度(不包括自身),因此在匹配時造成了一種跳躍式匹配。我們還是用上面的模式串來解釋:aaab
注意:我們預設把第乙個元素的next值設為-1
字首字尾
最大長度0-1
1∅∅0
2aa1
3a,aa
aa,a
2next[loopofpattern] = nextvalue, 我們這裡利用遞迴的思想求出next[loopofpattern+1]的值:
如果p[loopofpattern] = p[nextvalue],則next[nexvalue+1] = next[nextvalue] + 1;
如果p[loopofpattern] != p[nextvalue],則令nextvalue = next[nextvalue],如果此時p[loopofpattern] == p[nextvalue],則next[loopofpattern+1] = nextvalue+1;
如果不相等,則繼續遞迴字首索引,令nextvalue=next[nextvalue],繼續判斷,直至nextvalue=-1(即nextvalue=next[0])或者p[loopofpattern]=p[nextvalue]為止
國際慣例,上**
private
static
int[
]getnext
(string pattern)
else
}return next;
}
來烤饃片咯(誤
2.烤饃片 三 烤好了 總結幼稚 樸素 字串匹配法的時間複雜度為o n 並且指示主串的指標要來回回溯,看起來非常的不聰明。此時採用kmp演算法,應用next陣列,使得指示主串的指標不進行回溯且將時間複雜度降為o m n 寫的有點粗略 貼出來手寫筆記 思路 虛擬乙個重複的模式串並定義next j t ...
java 模式匹配
1 參加原始碼subjectdnx509principalextractor private pattern subjectdnpattern public object extractprincipal x509certificate clientcert no matching pattern ...
模式匹配演算法
brute force演算法 kmp演算法 kmp演算法的改進 模式匹配 子串的定位操作被叫做串的模式匹配。串相等 串長度相等且各個對應位置的字元都相等。當兩個串不相等時,判斷兩個串大小的方法 給定兩個串 s1 a1a2a3a4 an 和s2 b1b2b3b4 bm 當滿足以下條件之一時,s1n存在...