模式匹配(Java) 烤饃片演算法

2021-09-10 08:57:14 字數 3302 閱讀 8412

模式匹配是資料結構中字串的一種基本運算。

由於字串我們學習過了,大部分操作都比較清楚,但是模式匹配相對來說操作稍微有些難度,所以我們在這裡簡單的進行講述。

模式匹配的具體操作如下:給定乙個子串(也稱為模式串),要求在某個字串中找出與該子串相同的所有子串。

我們在此講述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存在...