四種最常見的字串匹配演算法概述

2022-09-09 06:42:08 字數 4561 閱讀 8898

bf演算法,即暴力(brute force)演算法,是普通的模式匹配演算法,bf演算法的思想就是將目標串s的第乙個字元與模式串t的第乙個字元進行匹配,若相等,則繼續比較s的第二個字元和 t的第二個字元;若不相等,則比較s的第二個字元和t的第乙個字元,依次比較下去,直到得出最後的匹配結果。bf演算法是一種蠻力演算法。

def

*****_matching(t, p):

m, n =len(p), len(t)

i, j =0, 0

while i < m and j < n: #

i==m means a matching

if p[i] == t[j]: #

ok! consider next char in p

i, j = i + 1, j + 1

else: #

no! consider next position in t

i, j = 0, j - i + 1

if i == m: #

find a matching, return its index

return j -i

return -1 #

no matching, return special value

t = "

aabababababbbbaababaaaababababbab

"p = "

abbab

"print(*****_matching(t, p))

kmp演算法是一種改進的字串匹配演算法,由d.e.knuth,j.h.morris和v.r.pratt提出的,因此人們稱它為克努特—莫里斯—普拉特操作(簡稱kmp演算法)。kmp演算法的核心是利用匹配失敗後的資訊,儘量減少模式串與主串的匹配次數以達到快速匹配的目的。具體實現就是通過乙個next()函式實現,函式本身包含了模式串的區域性匹配資訊。kmp演算法的時間複雜度o(m+n)。kmp演算法是各大教科書上的看家絕學,曾被投票選為當今世界最偉大的十大演算法之一;但是晦澀難懂,並且十分難以實現。

def

kmp_matching(t, p):

"""kmp字串匹配的另乙個版本, 稍許修改(非本質).

將gen_pnext定義為區域性函式.

"""def gen_pnext(p): #

p = "abbab"

"""生成p中各i的下一檢查位置表,稍許優化版本.

"""i, k, m = 0, -1, len(p)

pnext = [-1] * m #

初始化乙個陣列

while i < m - 1: #

generate pnext[i+1]

if k == -1 or p[i] ==p[k]:

i, k = i + 1, k + 1

if p[i] ==p[k]:

pnext[i] =pnext[k]

else

: pnext[i] =k

else

: k =pnext[k]

return

pnext

j, i =0, 0

n, m =len(t), len(p)

pnext =gen_pnext(p)

while j < n and i < m: #

i==m means a matching

while i >= 0 and t[j] !=p[i]:

i =pnext[i]

j, i = j + 1, i + 1

if i == m: #

找到匹配, 返回其下標

return j -i

return -1 #

不存在匹配, 返回特殊值

t = "

aabababababbbbaababaaaababababbab

"p = "

abbab

"print(kmp_matching(t, p))

def

getbmbc(pattern):

#預生成壞字元表

bmbc =dict()

for i in range(len(pattern) - 1):

char =pattern[i]

#記錄壞字元最右位置(不包括模式串最右側字元)

bmbc[char] = i + 1

return

bmbc

defgetbmgs(pattern):

#預生成好字尾表

bmgs =dict()

#無字尾僅根據壞字移位符規則

bmgs[''] =0

for i in

range(len(pattern)):

#好字尾

gs = pattern[len(pattern) - i - 1:]

for j in range(len(pattern) - i - 1):

#匹配部分

ngs = pattern[j:j + i + 1]

#記錄模式串中好字尾最靠右位置(除結尾處)

if gs ==ngs:

bmgs[gs] = len(pattern) - j - i - 1

return

bmgs

defbm(string, pattern):

"""boyer-moore演算法實現字串查詢

"""m =len(pattern)

n =len(string)

i =0

j =m

indies =

bmbc = getbmbc(pattern=pattern) #

壞字元表

bmgs = getbmgs(pattern=pattern) #

好字尾表

while i while (j >0):

if i + j - 1 >= n: #

當無法繼續向下搜尋就返回值

return

indies

#主串判斷匹配部分

a = string[i + j - 1:i +m]

#模式串判斷匹配部分

b = pattern[j - 1:]

#當前位匹配成功則繼續匹配

if a ==b:

j = j - 1

#當前位匹配失敗根據規則移位

else

: i = i + max(bmgs.setdefault(b[1:], m), j - bmbc.setdefault(string[i + j - 1], 0))

j =m

#匹配成功返回匹配位置

if j ==0:

i += 1j =len(pattern)

t = "

aabababababbbbaababaaaababababbab

"p = "

abbab

"print(bm(t, p))

sunday演算法是daniel m.sunday於2023年提出的字串模式匹配。其核心思想是:在匹配過程中,模式串發現不匹配時,演算法能跳過盡可能多的字元以進行下一步的匹配,從而提高了匹配效率。目前發現的最高效且容易理解的演算法。

def

sunday_match_str(main_str, find_str):

""":param main_str: 主串

:param find_str: 模式串

:return: 返回第乙個匹配到模式串中第乙個字元在主串中的下標

"""m, f =0, 0

m_len, f_len =len(main_str), len(find_str)

while m if main_str[m] ==find_str[f]:

m, f = m + 1, f + 1

if f ==f_len:

return m - f_len #

此時找到了第乙個匹配到的下標

continue

else

: flag = m - f +f_len

if flag > m_len - 1: #

main_str下標越界,沒有找到匹配的串

return -1check_exits =find_str.rfind(main_str[flag])

if check_exits != -1: #

在find_str中有匹配

jump = f_len - check_exits #

移動的步長

m, f = m - f +jump, 0

else: #

在find_str中無匹配

jump = f_len + 1 #

移動的步長

m, f = m - f +jump, 0

else

:

return -1t = "

aabababababbbbaababaaaababababbab

"p = "

abbab

"print(sunday_match_str(t, p))

常見的四種排序演算法

void bubblesort int a,int size,int order order為1代表公升序,氣泡排序演算法 void selectsort int a,int size,int order order為1代表公升序,選擇排序演算法 if k i void insertsort int...

四種PHP定義字串的方式

閱讀目錄 1 簡介 在php中這門語言中,因為是弱型別語言,因此使用變數時不需提前定義即可使用。我們在使用php進行開發的時候,大多數使用雙引號 單引號進行定義字串。既然有這兩種方式,那麼他們之間肯定是有區別的。並且,除了單雙引號定義字串這兩種方式外,php還增加了heredoc和nowdoc這兩種...

PHP定義字串的四種方式

1 單引號 在單引號中,任何特殊字元都會按原樣輸出 除 和 將會被轉義輸出 僅僅只有單引號 反斜槓被轉義 2 雙引號 在雙引號中,遇到 將會解析該變數 雙引號中會轉義反斜槓的轉義字元 單雙引號之間的區別 雙引號會替換變數的值,而單引號會把它當做字串輸出。對於轉義的支援 效能速度問題,由於雙引號中的字...