国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

腳本之家,腳本語言編程技術及教程分享平臺!
分類導航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務器之家 - 腳本之家 - Python - 淺談Python描述數據結構之KMP篇

淺談Python描述數據結構之KMP篇

2020-09-07 00:10夏悠然然 Python

這篇文章主要介紹了Python描述數據結構之KMP篇,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

前言

本篇章主要介紹串的KMP模式匹配算法及其改進,并用Python實現KMP算法。

1. BF算法

BF算法,即

undefined

Bruce−Force算法,又稱暴力匹配算法。其思想就是將主串S的第一個字符與模式串T的第一個字符進行匹配,若相等,則繼續比較S的第二個字符和T的第二個字符;若不相等,則比較S的第二個字符和T的第一個字符,依次比較下去,直到得出最后的匹配結果。

假設主串

undefined

S=ABACABAB,模式串

undefined

T=ABAB,每趟匹配失敗后,主串S指針回溯,模式串指針回到頭部,然后再次匹配,過程如下:

淺談Python描述數據結構之KMP篇

def BF(substrS, substrT):

if len(substrT) > len(substrS):

return -1

j = 0

t = 0

while j < len(substrS) and t < len(substrT):

if substrT[t] == substrS[j]:

j += 1

t += 1

else:

j = j - t + 1

t = 0

if t == len(substrT):

return j - t

else:

return -1

2. KMP算法

KMP算法,是由

undefined

D.E.Knuth、J.H.Morris、V.R.Pratt同時發現的,又被稱為克努特-莫里斯-普拉特算法。該算法的基本思路就是在匹配失敗后,無需回到主串和模式串最近一次開始比較的位置,而是在不改變主串已經匹配到的位置的前提下,根據已經匹配的部分字符,從模式串的某一位置開始繼續進行串的模式匹配。

就是這次匹配失敗時,下次匹配時模式串應該從哪一位開始比較。

BF算法思路簡單,便于理解,但是在執行時效率太低。在上述的匹配過程中,第一次匹配時已經匹配的

undefined

"ABA",其前綴與后綴都是

undefined

"A",這個時候我們就不需要執行第二次匹配了,因為第一次就已經匹配過了,所以可以跳過第二次匹配,直接進行第三次匹配,即前綴位置移到后綴位置,主串指針無需回溯,并繼續從該位開始比較。

前綴:是指除最后一個字符外,字符串的所有頭部子串。

后綴:是指除第一個字符外,字符串的所有尾部子串。

部分匹配值

undefined

(Partial

undefined

Match,PM):字符串的前綴和后綴的最長相等前后綴長度。

例如,

undefined

′a′的前綴和后綴都為空集,則最長公共前后綴長度為0;

undefined

′ab′的前綴為

undefined

{a},后綴為

undefined

{b},則最長公共前后綴為空集,其長度長度為0;

undefined

′aba′的前綴為

undefined

{a,ab},后綴為

undefined

{a,ba},則最長公共前后綴為

undefined

{a},其長度長度為1;

undefined

′abab′的前綴為

undefined

{a,ab,aba},后綴為

undefined

{b,ab,bab},則最長公共前后綴為

undefined

{ab},其長度長度為2。

前綴一定包含第一個字符,后綴一定包含最后一個字符。

淺談Python描述數據結構之KMP篇

1

如果模式串號位與主串當前位(箭頭所指的位置)不匹配,將模式串1號位與主串的下一位進行比較。next[0]=-1,這邊就是一個特殊位置了,即如果主串與模式串的第1位不相同,那么下次就直接比較各第2位的字符。

淺談Python描述數據結構之KMP篇

2

如果模式串號位與主串當前位不匹配,找最長公共前后綴,指針前面的子串為

undefined

1

"A",即最長公共前后綴為空集,其長度為0,則下次匹配時將模式串號位與主串的當前位進行比較。next[1]=0

淺談Python描述數據結構之KMP篇

3

如果模式串號位與主串當前位不匹配,找最長公共前后綴,指針前面的子串為

undefined

1

"AB",即最長公共前后綴為空集,其長度為0,則下次匹配時將模式串號位與主串的當前位進行比較。next[2]=0

淺談Python描述數據結構之KMP篇

4

如果模式串號位與主串當前位不匹配,找最長公共前后綴,指針前面的子串為

undefined

"ABA",即最長公共前后綴為

undefined

2

"A",其長度為1,則下次匹配時將前綴位置移到后綴位置,即模式串號位與主串的當前位進行比較。next[3]=1

淺談Python描述數據結構之KMP篇

5

如果模式串號位與主串當前位不匹配,找最長公共前后綴,指針前面的子串為

undefined

"ABAA",即最長公共前后綴為

undefined

2

"A",其長度為1,則下次匹配時將前綴位置移到后綴位置,即模式串號位與主串的當前位進行比較。next[4]=1

淺談Python描述數據結構之KMP篇

6

如果模式串號位與主串當前位不匹配,找最長公共前后綴,指針前面的子串為

undefined

"ABAAB",即最長公共前后綴為

undefined

3

"AB",其長度為2,則下次匹配時將前綴位置移到后綴位置,即模式串號位與主串的當前位進行比較。next[5]=2

淺談Python描述數據結構之KMP篇

7

如果模式串號位與主串當前位不匹配,找最長公共前后綴,指針前面的子串為

undefined

1

"ABAABC",即最長公共前后綴為空集,其長度為0,則下次匹配時將模式串號位與主串的當前位進行比較。next[6]=0

淺談Python描述數據結構之KMP篇

8

如果模式串號位與主串當前位不匹配,找最長公共前后綴,指針前面的子串為

undefined

"ABAABCA",即最長公共前后綴為

undefined

2

"A",其長度為1,則下次匹配時將模式串號位與主串的當前位進行比較。next[7]=1

綜上,可以得到模式串的next數組,發現沒有,把主串去掉也可以得到這個數組,即下次匹配時模式串向后移動的位數與主串無關,僅與模式串本身有關。

位編號 1 2 3 4 5 6 7 8
索引 0 1 2 3 4 5 6 7
模式串 A B A A B C A C
next -1 0 0 1 1 2 0 1

next數組,即存放的是每個字符匹配失敗時,對應的下一次匹配時模式串開始匹配的位置。

如何在代碼里實現上述流程呢?舉個栗子,藍色方框圈出的就是公共前后綴,假設next[j]=t:

淺談Python描述數據結構之KMP篇

undefined

Tj?=Tt?時,可以得到

undefined

next[j+1]=t+1=next[j]+1。這個時候

undefined

j=4,t=1(索引);

淺談Python描述數據結構之KMP篇

undefined

Tj??=Tt?時,即模式串

undefined

t位置與主串(并不是真正的主串)不匹配,則將下面的那個模式串移動到

undefined

next[t]位置進行比較,即

undefined

t=next[t],直到

undefined

Tj?=Tt?或

undefined

t=−1,當

undefined

t=−1時,

undefined

next[j+1]=0。這里就是

undefined

t=next[2]=0,即下次匹配時,模式串的第1位與主串當前位進行比較。

代碼如下:

def getNext(substrT):

next_list = [-1 for i in range(len(substrT))]

j = 0

t = -1

while j < len(substrT) - 1:

if t == -1 or substrT[j] == substrT[t]:

j += 1

t += 1

# Tj=Tt, 則可以到的next[j+1]=t+1

next_list[j] = t

else:

# Tj!=Tt, 模式串T索引為t的字符與當前位進行匹配

t = next_list[t]

return next_list

def KMP(substrS, substrT, next_list):

count = 0

j = 0

t = 0

while j < len(substrS) and t < len(substrT):

if substrS[j] == substrT[t] or t == -1:

# t == -1目的就是第一位匹配失敗時

# 主串位置加1, 匹配串回到第一個位置(索引為0)

# 匹配成功, 主串和模式串指針都后移一位

j += 1

t += 1

else:

# 匹配失敗, 模式串索引為t的字符與當前位進行比較

count += 1

t = next_list[t]

if t == len(substrT):

# 這里返回的是索引

return j - t, count+1

else:

return -1, count+1

3. KMP算法優化版

上面定義的next數組在某些情況下還有些缺陷,發現沒有,在第一個圖中,我們還可以跳過第3次匹配,直接進行第4次匹配。為了更好地說明問題,我們以下面這種情況為例,來優化一下KMP算法。假設主串

undefined

S=AAABAAAAB,模式串

undefined

T=AAAAB,按照KMP算法,匹配過程如下:

淺談Python描述數據結構之KMP篇

可以看到第2、3、4次的匹配是多余的,因為我們在第一次匹配時,主串

undefined

4

S的號位為模式串

undefined

4

T的號位就已經比較了,且

undefined

T3??=S3?,又因為模式串

undefined

T的4號位與其1、2、3號位的字符一樣,即

undefined

T3?=T2?=T1?=T0??=S3?,所以可以直接進入第5次匹配。

那么,問題出在哪里???我們結合著next數組看一下:

位編號 1 2 3 4 5
索引 0 1 2 3 4
模式串 A A A A B
next -1 0 1 2 3

問題在于,當

undefined

Tj??=Sj?時,下次匹配的必然是

undefined

Tnext[j]?與

undefined

Sj?,如果這時

undefined

Tnext[j]?=Tj?,那么又相當于

undefined

Tj?與

undefined

Sj?進行比較,因為它們的字符一樣,毫無疑問,這次匹配是沒有意義的,應當將

undefined

next[j]的值直接賦值為-1,即遇到這種情況,主串與模式串都從下一位開始比較。

所以,我們要修正一下next數組。

大致流程和上面求解next數組時一樣,這里就是多了一個判別條件,如果在匹配時出現了

undefined

Tnext[j]?=Tj?,我們就將next[j]更新為next

undefined

[next[j]

undefined

],直至兩者不相等為止(相當于了迭代)。在代碼里面實現就是,如果某個字符已經相等或者第一個next[j]數組值為-1(即

undefined

t=−1),且主串和模式串指針各后移一位時的字符仍然相同,那么就將當前的next[j]值更新為上一個next[j]數組值,更新后的數組命名為nextval。

代碼如下:

def getNextval(substrT):

nextval_list = [-1 for i in range(len(substrT))]

j = 0

t = -1

while j < len(substrT) - 1:

if t == -1 or substrT[j] == substrT[t]:

j += 1

t += 1

if substrT[j] != substrT[t]:

# Tj=Tt, 但T(j+1)!=T(t+1), 這個就和next數組計算時是一樣的

# 可以得到nextval[j+1]=t+1

nextval_list[j] = t

else:

# Tj=Tt, 且T(j+1)==T(t+1), 這個就是next數組需要更新的

# nextval[j+1]=上一次的nextval_list[t]

nextval_list[j] = nextval_list[t]

else:

# 匹配失敗, 模式串索引為t的字符與當前位進行比較

t = nextval_list[t]

return nextval_list

對KMP的優化其實就是對next數組的優化,修正后的next數組,即nextval數組如下:

位編號 1 2 3 4 5
索引 0 1 2 3 4
模式串 A A A A B
nextval -1 -1 -1 -1 3

下面就測試一下:

if __name__ == '__main__':

S1 = 'ABACABAB'

T1 = 'ABAB'

S2 = 'AAABAAAAB'

T2 = 'AAAAB'

print('*' * 50)

print('主串S={0}與模式串T={1}進行匹配'.format(S1, T1))

print('{:*^25}'.format('KMP'))

next_list1 = getNext(T1)

print('next數組為: {}'.format(next_list1))

index1_1, count1_1 = KMP(S1, T1, next_list1)

print('匹配到的位置(索引): {}, 匹配次數: {}'.format(index1_1, count1_1))

print('{:*^25}'.format('KMP優化版'))

nextval_list1 = getNextval(T1)

print('nextval數組為: {}'.format(nextval_list1))

index1_2, count1_2 = KMP(S1, T1, nextval_list1)

print('匹配到的位置(索引): {}, 匹配次數: {}'.format(index1_2, count1_2))

print('')

print('*' * 50)

print('主串S={0}與模式串T={1}進行匹配'.format(S2, T2))

print('{:*^25}'.format('KMP'))

next_list2 = getNext(T2)

print('next數組為: {}'.format(next_list2))

index2_1, count2_1 = KMP(S2, T2, next_list2)

print('匹配到的位置(索引): {}, 匹配次數: {}'.format(index2_1, count2_1))

print('{:*^25}'.format('KMP優化版'))

nextval_list2 = getNextval(T2)

print('nextval數組為: {}'.format(nextval_list2))

index2_2, count2_2 = KMP(S2, T2, nextval_list2)

print('匹配到的位置(索引): {}, 匹配次數: {}'.format(index2_2, count2_2))

運行結果如下:

淺談Python描述數據結構之KMP篇

運行的結果和我們分析的是一樣的,不修正next數組時,主串

undefined

S=ABACABAB與模式串

undefined

T=ABAB匹配時需要4次,主串

undefined

S=AAABAAAAB與模式串

undefined

T=AAAAB匹配時需要5次;修正next數組后,主串

undefined

S=ABACABAB與模式串

undefined

T=ABAB匹配時需要3次,主串

undefined

S=AAABAAAAB與模式串

undefined

T=AAAAB匹配時僅需要2次。

結束語

在寫本篇博客之前也是反復看參考書、視頻,邊畫圖邊去理解它,這篇博客也是反復修改了好幾次,最終算是把KMP解決掉了,有關字符串知識的復習也算是基本結束,下面就是刷題了(雖然在LeetCode做過了幾道題)。到此這篇關于Python描述數據結構之KMP篇的文章就介紹到這了,更多相關Python KMP內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://blog.csdn.net/qq_42730750/article/details/108058105

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 一区二区三区精品视频 | 亚洲经典一区 | 伊人网在线视频观看 | 国产一区| 久久精品亚洲精品国产欧美kt∨ | 精品国产一区二区三区久久 | 免费久久精品 | 精品视频久久 | 国产一区免费 | 黄色在线 | 成人性大片免费观看网站 | 99免费在线播放99久久免费 | 国产超碰人人爽人人做人人爱 | 操操网站 | 99免费视频 | 国产成人a亚洲精品 | 伊人网电影| 久久久久久一区 | 久久久久久91亚洲精品中文字幕 | 久草社区 | 久久噜噜噜精品国产亚洲综合 | 亚洲精品成人 | 伊人6| 欧美日一区 | 欧美在线观看视频一区二区 | 日本不卡免费新一二三区 | 综合另类 | 日本一区二区三区精品视频在线观看 | 三级在线网 | 欧美一区二区三区精品 | 中文字幕精品一区久久久久 | 国产日韩一区二区三区 | 精品国产一区二区三区久久久蜜 | 国产精品福利视频 | 高清av电影 | 亚洲一区精品在线 | 国产欧美日韩综合精品一区二区 | 成人午夜小视频 | 欧美激情一区 | 国产黄a一级 | 国产欧美精品一区二区三区 |