KMP字元匹配

2021-10-06 04:31:04 字數 3085 閱讀 1661

kmp 演算法是在 s中查詢子串 p,如果存在,返回這個子串的起始索引,否則返回空列表
輸入:文字串s='bbc abcdab abcdabcdabde',模式串p='abcdabd'

輸出:[15]

解釋:起始索引等於 15 長度為 7 的子串是 "abcdabde"

s='abcdabcdabd'

p='abcdabd'

當確定s的第7個元素和p的第7個元素不同時,下一次比較希望能如下

abcdabcdabd

abcdabd

這樣我們就需要求得模式串p字首字尾的公共元素的最大長度表

# kmp 演算法是在 s中查詢子串 p,如果存在,返回這個子串的起始索引,否則返回空列表

# 輸入:文字串s='bbc abcdab abcdabcdabde',模式串p='abcdabd'

# 輸出:[15]

# 解釋:

# 起始索引等於 15 長度為 7 的子串是 "abcdabde"

# 思路:

# s='abcdabcdabd'

# p='abcdabd'

# 當確定s的第7個元素和p的第7個元素不同時,下一次比較希望能如下

# 'abcdabcdabd'

# 'abcdabd'

# 這樣我們就需要求得模式串p字首字尾的公共元素的最大長度表

def get_next(p,p_len):

# 得到模式串p字首字尾的公共元素的最大長度表p_next

# 例如:

# p='abcdabd'

# p_next=[0,0,0,0,1,2,0]

# 解釋:

# 字首字尾解釋: 對於'abc'-->字首:'a','ab';字尾:'c','bc'

# p_next[i] --> i==0時,'a'字首字尾的公共元素的最大長度為0

# i==1時,'ab'字首字尾的公共元素的最大長度為0

# i==2時,'abc'字首字尾的公共元素的最大長度為0

# i==3時,'abcd'字首字尾的公共元素的最大長度為0

# i==4時,'abcda'字首字尾的公共元素'a'長度為1

# i==5時,'abcdab'字首字尾的公共元素'ab'長度為2

# i==6時,'abcdabd'字首字尾的公共元素的最大長度為0

#p_next的第乙個元素必定為0

p_next=[0]*p_len

for i in range(1,p_len):

#確定next[i]值時,我們只需比較前一狀態字首字尾的公共元素的下一位元素和當前位元素是否相同

#例如i==5時,此時我們關注的字串位'abcdab',next=[0, 0, 0, 0, 1, 0, 0],

# 我們已求得i=4時字首字尾的公共元素'a'長度為1,我們這裡比較p的第2個元素'b'是否等於p的第6個元素'b'

# 因為我們已經在i=4時已經確定了p[:1]==p[5-1:5]

if p[i]==p[p_next[i-1]]:

#若相同則是前一狀態的長度加一

p_next[i]=p_next[i-1]+1

#不相等時判斷是否和首位元素是否相同

elif p[i]==p[0]:

p_next[i]=1

#不然就是無公共元素

else:

p_next[i]=0

return p_next

def kmp(s,p):

# 文字串s的長度

s_len=len(s)

# 模式串p的長度

p_len=len(p)

# s,p搜尋時的下標

s_index,p_index=0,0

# 得到模式串p字首字尾的公共元素的最大長度表p_next

p_next=get_next(p,p_len)

# 儲存結果列表

res=

# 用s_index來控制迴圈結束

while s_index# 用p_index來控制s_index的變化以及判斷是否匹配成功

if p_index# 若s的當前字元和p的當前字元相同,則比較s的下一字元和p的下一字元

if s[s_index]==p[p_index]:

s_index+=1

p_index+=1

# 若s當前字元是和p的首字元比較,且不相同,則比較s的下一字元和p的首字元

elif p_index==0:

s_index+=1

# 若s和p已比較了一些字元相同,在當前字元不相同時,則根據p_next確定p_index

else:

# 例如:

# s = 'abcdabc'

# p = 'abcdabd'

# s_index=6

# p_index=6

# p_next=[0,0,0,0,1,2,0]

# 這裡我們要的結果就是s_index=6,p_index=2

# 即我們希望下一次這樣比較(比較的是對齊的兩個c)

# abcdabc

# abcdabd

p_index=p_next[p_index-1]

# p_index==p_len時說明字元完全匹配成功,儲存初始下標並繼續比較

if p_index==p_len:

# 當前s的下標減去模式串s的長度就是匹配成功初始的下標

# 跟上面得到p_index一樣的方式繼續匹配,因為這裡已經匹配成功了,所以直接是p_next的最後乙個元素

p_index=p_next[-1]

return res

s='bbc abcdab abcdabcdabcd'

p='abcdabcd'

res=kmp(s,p)

print(res)

for begin in res:

print(s[begin:begin+len(p)])

KMP字元匹配

在kmp 中,主要是尋找模式字串的字首和字尾的最長的共有元素的長度。以 abcdabd 為例,a 的字首和字尾都為空集,共有元素的長度為0 ab 的字首為 a 字尾為 b 共有元素的長度為0 abc 的字首為 a,ab 字尾為 bc,c 共有元素的長度0 abcd 的字首為 a,ab,abc 字尾為...

字元匹配kmp演算法

前言 之前對kmp演算法雖然了解它的原理,即求出p0 pi的最大相同前字尾長度k 但是問題在於如何求出這個最大前字尾長度呢?我覺得網上很多帖子都說的不是很清楚,總感覺沒有把那層紙戳破,後來翻看演算法導論,32章 字串匹配雖然講到 了對前1.kmp演算法的原理 本部分內容 字串匹配是計算機的基本任務之...

字元匹配 KMP演算法

problem description 給定兩個字串string1和string2,判斷string2是否為string1的子串。input 輸入包含多組資料,每組測試資料報含兩行,第一行代表string1 長度小於1000000 第二行代表string2 長度小於1000000 string1和s...