我遇到了用于子字符串搜索的KMP算法,并在python中实现了它。后来,我发现in
运算符也可以用于此问题,因此我决定比较它们的性能。令我惊讶的是,in
比KMP算法快得多,我决定仔细研究in
。
我发现in
在字符串中实现了__contains__
方法,该字符串用于Datamodel doc中建议的包含检查。但是无法进一步了解为什么它更快。
这是我对KMP算法的实现:
def lps(pattern):
start_ind = 0
lps_list = [0]
for j in pattern[1:]:
if(j == pattern[start_ind]):
lps_list.append(start_ind)
start_ind += 1
else:
start_ind = 0
lps_list.append(start_ind)
return lps_list
def kmp(search, pattern):
lps_list = lps(pattern)
pat_ind = 0
for j in search:
if(pat_ind == len(pattern)):
return True
if(j == pattern[pat_ind]):
pat_ind += 1
continue
while(j != pattern[pat_ind] and pat_ind != 0):
pat_ind = lps_list[pat_ind - 1]
if(pat_ind == 0 and j == pattern[pat_ind]):
pat_ind += 1
else:
if(pat_ind == len(pattern)):
return True
return False
驱动程序块:
start = timeit.default_timer()
print('Found!!') if(kmp(search, pattern)) else print('Nope')
print(f'KMP algorithm: {(timeit.default_timer() - start):0.8e}')
start = timeit.default_timer()
print('Found!!') if(pattern in search) else print('Nope')
print(f'in operator: {(timeit.default_timer() - start):0.8e}')
测试用例和结果:
search = ''.join(['a' for _ in range(10000)] + ['b'])
pattern = ''.join(['a' for _ in range(1000)] + ['b'])
Found!!
KMP algorithm: 4.42536000e-03
Found!!
in operator: 3.72060003e-05
我希望KMP算法不会像结果所示那样慢,因为它是一个不错的子字符串搜索算法。我不知道是不是我的测试用例遗漏了某些东西,或者是由于Python的字符串存储方式所致。
答案 0 :(得分:1)
正如对该问题的评论中所建议的那样,内部字符串搜索算法在最佳情况下比KMP算法更快,但在最坏情况下也更慢。最坏的情况更罕见。这里是一些background及其实现的source code。而且它在C语言中实现的事实使其变得更快。
以下是str.__contains__
和结果的最坏情况:
search = 'a' * 10000000 + 'ba'
pattern = 'a' * 10000 + 'ba'
Found!!
KMP algorithm: 3.29188600e+00
Found!!
in operator: 3.85637655e+01