我已经创建了这个脚本来计算python中的string similarity。有什么方法可以让它跑得更快吗?
tries = input()
while tries > 0:
mainstr = raw_input()
tot = 0
ml = len(mainstr)
for i in xrange(ml):
j = 0
substr = mainstr[i:]
ll = len(substr)
for j in xrange(ll):
if substr[j] != mainstr[j]:
break
j = j + 1
tot = tot + j
print tot
tries = tries - 1
编辑:应用了一些优化后,这就是代码,但这还不够!
tries = int(raw_input())
while tries > 0:
mainstr = raw_input()
tot = 0
ml = len(mainstr)
for i in xrange(ml):
for j in xrange(ml-i):
if mainstr[i+j] != mainstr[j]:
break
j += 1
tot += j
print tot
tries = tries - 1
编辑2 :代码的第三个版本。它仍然没有去!
def mf():
tries = int(raw_input())
for _ in xrange(tries):
mainstr = raw_input()
tot = 0
ml = len(mainstr)
for i in xrange(ml):
for j in xrange(ml-i):
if mainstr[i+j] != mainstr[j]:
break
j += 1
tot += j
print tot
mf()
答案 0 :(得分:2)
您可以跳过循环内的内存分配。 substr = mainstr[i:]
不必要地分配新字符串。您只能在substr[j] != mainstr[j]
中使用它,相当于mainstr[i + j] != mainstr[j]
,因此您不需要构建substr
。
内存分配很昂贵,因此您希望在紧密循环中避免使用它们。
答案 1 :(得分:2)
如果您使用i = mainstr.find(mainstr[0], i+1)
而不是检查所有i
,则可以通过常数因子对其进行改进。 i == 0的特例也可以提供帮助。
将代码放在函数中。它也可以通过一个恒定的因素加快速度。
使用for ... else: j += 1
避免在每一步增加j
。
尝试找到比O(n ** 2)更好的算法,该算法利用了比较字符串所有后缀的事实。
最多straight-forward C implementation比CPython快100倍(Pypy快10-30倍)并通过挑战:
import os
def string_similarity(string, _cp=os.path.commonprefix):
return sum(len(_cp([string, string[i:]])) for i in xrange(len(string)))
for _ in xrange(int(raw_input())):
print string_similarity(raw_input())
上述优化仅提供了几个百分点的改进,并且它们不足以在CPython中传递挑战(Python时间限制只有8倍大)。
在CPython之间几乎没有区别:
def string_similarity(string):
len_string = len(string)
total = len_string # similarity with itself
for i in xrange(1, len_string):
for n, c in enumerate(string[i:]):
if c != string[n]:
break
else:
n += 1
total += n
return total
和
def string_similarity(string):
len_string = len(string)
total = len_string # similarity with itself
i = 0
while True:
i = string.find(string[0], i+1)
if i == -1:
break
n = 0
for n in xrange(1, len_string-i):
if string[i+n] != string[n]:
break
else:
n += 1
total += n
return total
答案 2 :(得分:1)
对于这样的简单数字脚本,您只需要做两件事:
使用PyPy(它没有复杂的依赖关系,速度会快得多)
将大部分代码放在一个函数中。这大大加快了CPython和PyPy的速度。而不是:
some_code
做的:
def main():
some_code
if __name__ == '__main__':
main()
这就是它。
干杯, fijal
答案 3 :(得分:0)
这是我的。它通过了测试用例,但可能不是绝对最快的。
import sys
def simstring(string, other):
val = 0
for l, r in zip(string, other):
if l != r:
return val
val += 1
return val
dsize = sys.stdin.readline()
for i in range(int(dsize)):
ss = 0
string = sys.stdin.readline().strip()
suffix = string
while suffix:
ss += simstring(string, suffix)
suffix = suffix[1:]
sys.stdout.write(str(ss)+"\n")