【发布时间】:2016-12-17 13:26:58
【问题描述】:
我已经实现了下面的朴素字符串搜索算法('find')。它尽可能简单。然而,我在“GeeksforGeeks”('search') 上找到了另一种方法,它看起来具有更好的复杂性。当我对大字符串进行测试时,结果截然不同但相反。
1st:将字符串切成模式长度并进行比较。向前移动一个字符切片并进行比较。这应该是什么复杂性?
def find(pat, txt):
size = len(pat)
for i in range( len(txt) -size + 1 ):
if txt[i : i + size] == pat:
print 'Pattern found at index %s'%(i)
2nd:逐个字符比较。如果一个字符不匹配中断。否则继续。最后,如果所有字符匹配打印结果。向前移动一个字符。这应该是什么复杂性?
def search(pat, txt):
M = len(pat)
N = len(txt)
for i in xrange(N-M+1):
status = 1
for j in xrange(M):
if txt[i+j] != pat[j]:
status = 0
break
if j == M-1 and status != 0:
print "Pattern found at index " + str(i)
时序测试用例:
testString = ''.join([ 'a' for _ in range(1000*100)] ) + 'b'
testPattern = ''.join([ 'a' for _ in range(100*100) ]) + 'b'
import cProfile
cProfile.run('find(testPattern, testString)')
cProfile.run('search(testPattern, testString)')
为find
Pattern found at index 90000
90007 function calls in 0.160 seconds
对于search
Pattern found at index 90000
5 function calls in 135.951 seconds
在我的算法find 中,我进行切片和比较。切片的时间复杂度是 O(k),类似地为了比较它应该需要另一个 O(k) 虽然不确定。
Python Time Complexity
在search 中,我们只运行了“k”次循环。所以它不应该有更好的时间复杂度。
【问题讨论】:
-
算法 A 在给定测试中的表现是否优于算法 B,以及算法 A 的时间复杂度是否优于算法 B,这是两个独立的问题。一方面——复杂性结果是渐近的。另一方面,big-O 表示法中的比例常数可以隐藏大量的低效率。我不知道这里发生了什么——但你似乎在比较苹果和橘子。
-
@JohnColeman 但我们总是可以谈论最坏的情况。我尝试使用不同的字符串。但总的来说,第一种算法更快,而且也有很大的不同。我试图了解我在哪里出错了。假设只是针对这种情况,为什么会出现这些结果?
-
您可以对此进行分析并找出,查找标准的 python 分析工具。我没有看到这两种算法之间的实质性区别,但是,您的实现依赖于运行时完成的本机字符串比较,另一个实现在纯 python 中逐个字符地进行比较。这要慢得多。
-
在 Python 中,算法上“较慢”的方法比在解释代码中实现的算法上“较快”的算法更好地利用内置方法(在优化的编译 C 中运行)执行更好的算法并不少见。这是可以隐藏在比例常数中的低效率之一。
-
第二种方法是原生字符串比较在 Python 中的工作方式。如果第一个字符不匹配,则无需查看其余字符。不同之处在于它以更优化的方式实现。