アルゴリズム-KMP文字列マッチングとそのPython実装
14352 ワード
KMPモードマッチングアルゴリズム
1.考え方分析
参照先:https://blog.csdn.net/lemon_tree12138/article/details/48488813
1.1知識の補充
マッチングモードでは、各最適接頭辞(最適接頭辞については「アルゴリズム導論」32章の内容を参照することができる)Sにおいて、Sの自己の最長ではない1つが最適接尾辞(最適接尾辞については「アルゴリズム導論」32章の内容を参照することができる)に等しい最適接頭辞SSである.この言葉にはいくつかの早口が聞こえるかもしれませんが、次の例で説明します.
マッチングモードP:ababaca
Pの最適プレフィックスS=ababaを選択すると,SS=abaとなる.SSはSの最適接頭辞であり、Sの最適接尾辞であり、最も長いからである.
1.2例の説明
KMPアルゴリズムの鍵は、主文字列のマッチング位置「ポインタ」を使用して遡及する必要がない重複マッチングを排除することです.ここでは小さな例を挙げてみましょう.
主文字列T:fababadaaswababababacaマッチングモードP:ababaca
もしこのときTの7位(fababa[d]aaswababababababa)とPの6位(ababa[c]a)をマッチングしていて,マッチングに失敗していたら.素朴なマッチングパターンに対してはTの「ポインタ」が(fa[b]abadaaswabababacaに遡り,Pの「ポインタ」が([a]bababababababacaに遡る)である.Tの「針」の遡及は、多くの時間を浪費したに違いない.
P(ababaca)を再確認し、6位のマッチングを開始すると、前の5位のマッチングが完了しました.また,[aba]ba=ab[aba]である.では,Tに対してfab[aba]daaswababacaの3ビットは既にマッチングされており,マッチングはP(aba)caであり,[aba]ba=ab[aba]である.ここで選択された最適なサブストリングは、現在の一致文字列Tの一部(aba)全体を表すことができ、一致時に接頭辞が失効すると、接尾辞から直接一致することが理解される.このとき,T「ポインタ」を直接fab[aba]の後ろの要素(すなわちi=6,P「ポインタ」は[aba]の後ろの要素(すなわちi=3)を指すことができる.
2コード実装
import time
import numpy as np
class SimpleMatching():
def getIndexOfPinT(self, t, p):
if t is None or p is None:
return None
indexes = []
for i in range(len(t) - len(p) + 1):
for j in range(len(p)):
if t[i + j] == p[j]:
if j == len(p) - 1:
indexes.append(i)
continue
break
return indexes
class KmpMatching():
def getNext(self, text):
if text is None:
return None
lengths = np.zeros(len(text), dtype=int)
for i in range(len(text)):
sub = text[0: i+1]
maxlen = 0
for j in range(len(sub)-1):
subChild = sub[0: j+1]
if sub.endswith(subChild) and len(subChild)>maxlen:
maxlen = len(subChild)
lengths[i] = maxlen
return lengths
def getIndexOfPinT(self, t, p):
if t is None or p is None:
return None
indexes = []
next = self.getNext(p)
indexT = 0
indexP = 0
while indexT < len(t):
if t[indexT] == p[indexP]:
indexP += 1
indexT += 1
elif indexP == 0:
indexT += 1
else:
indexP = next[indexP - 1]
if indexP == len(p):
indexes.append(indexT - indexP)
indexP = 0
return indexes
if __name__ == "__main__":
t = "fababadaaswababaca"*100000
p = "ababaca"
start_SimpleMatch = time.time()
simple_match = SimpleMatching()
indexes1 = simple_match.getIndexOfPinT(t, p)
print(indexes1)
end_SimpleMatch = time.time()
print("The time of SimpleMatching is: ", end_SimpleMatch-start_SimpleMatch)
start_KMPMatch = time.time()
KMP_match = KmpMatching()
indexes2 = KMP_match.getIndexOfPinT(t, p)
print(indexes2)
end_KMPMatch = time.time()
print("The time of KMP-Matching is: ", end_KMPMatch - start_KMPMatch)
>>> The time of SimpleMatching is: 1.203505516052246
The time of KMP-Matching is: 1.116056203842163
結果から,KMPアルゴリズムは素朴なマッチングよりも高速であることが分かった.