問題:給定兩個字符串a="sdfaabcddsdfssd",b="df"找出字串b在a中的下標位置。
樸素模式匹配算法:
def str_index(a,b,pos=0):
i = pos
j = 0
while i < len(a) and j < len(b):
if a[i] == b[j]:
j += 1
i += 1
else:
i = i-j+1
j = 0
if j == len(b):
return i-j
else:
return -1
KMP算法:需創建next_arr數組,存放b串中 每個下標位置前(不包含當前下標) 字符串的前綴和後綴相同的個數,作用是:在字符匹配失敗時,判定應該繼續從b串的哪一位字符開始繼續匹配
def kmp_next(b):
next_arr = [-1] * len(b)
i = 0
j = -1
while i < len(b)-1:
if j == -1 or b[j] == b[i]:
i += 1
j += 1
next_arr[i] = j
else:
j = next_arr[j]
return next_arr
def kmp_index(a,b,pos=0):
i = pos
j = -1
kmp_next_arr = kmp_next(b)
while i < len(a) and j < len(b):
if j == -1 or a[i] == b[j]:
i += 1
j += 1
else:
j = kmp_next_arr[j]
if j == len(b):
return i - j
else:
return -1
if __name__ == '__main__':
# index = str_index('sdfaabcddsdfssd','sdf',1)
index = kmp_index('sdfaabcddsdfssd','df')
KMP的改進算法:修改了next_arr數組的獲取方法。
主要邏輯:
1.假設b串中當前需要判斷的位置下標爲:k。
2.k位置下對應的 前字符串前後綴字符重複個數爲:n,即next_arr[k]=n。
3.n位置下對應的 前字符串前後綴字符重複個數爲:nn,即next_arr[n]=nn.
則判斷b[k]與b[n]的值是否相同,若相同next_arr[k]=nn,若不同,下標k對應的值不變,還是next_arr[k] = n
def kmp_next_optimize(b):
next_arr = [-1] * len(b)
i = 0
j = -1
while i < len(b)-1:
if j == -1 or b[j] == b[i]:
i += 1
j += 1
if b[j] != b[i]:
next_arr[i] = j
else:
next_arr[i] = next_arr[j]
else:
j = next_arr[j]
return next_arr
若代碼難以理解可參考博客:https://blog.csdn.net/v_JULY_v/article/details/7041827