如何进一步优化这个python脚本?

如何进一步优化这个python脚本?,python,optimization,micro-optimization,Python,Optimization,Micro Optimization,我创建这个脚本是为了在python中计算。有什么办法可以让它跑得更快吗 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(l

我创建这个脚本是为了在python中计算。有什么办法可以让它跑得更快吗

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()

您可以跳过循环内的内存分配
substr=mainstr[i::
不必要地分配新字符串。您只能在
substr[j]!=mainstr[j]
,相当于
mainstr[i+j]!=mainstr[j]
,因此不需要构建
substr


内存分配非常昂贵,因此您希望避免在紧循环中进行内存分配。

您可以跳过循环中的内存分配
substr=mainstr[i::
不必要地分配新字符串。您只能在
substr[j]!=mainstr[j]
,相当于
mainstr[i+j]!=mainstr[j]
,因此不需要构建
substr


内存分配是昂贵的,因此您希望避免它们在紧循环中出现。

如果您使用
i=mainstr.find(mainstr[0],i+1)
而不是检查所有
i
,您可以通过一个常数因子来改进它。i==0的特殊情况也会有所帮助

将代码放入函数中。它还可能以一个恒定的因子加速事情

对…使用
。。。否则:j+=1
,以避免在每个步骤中增加
j

尝试找到一个比O(n**2)更好的算法,该算法利用比较字符串所有后缀的事实

most比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的时间限制只比CPython大8倍)

以下各项之间几乎没有区别(在CPython中):

以及:


如果使用
i=mainstr.find(mainstr[0],i+1)
而不是检查所有
i
,则可以通过一个常数因子来改进它。i==0的特殊情况也会有所帮助

将代码放入函数中。它还可能以一个恒定的因子加速事情

对…使用
。。。否则:j+=1
,以避免在每个步骤中增加
j

尝试找到一个比O(n**2)更好的算法,该算法利用比较字符串所有后缀的事实

most比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的时间限制只比CPython大8倍)

以下各项之间几乎没有区别(在CPython中):

以及:


这是我的。它通过了测试用例,但可能不是绝对最快的

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")

这是我的。它通过了测试用例,但可能不是绝对最快的

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")

对于这种简单的数字脚本,您只需做两件事:

  • 使用PyPy(它没有复杂的依赖关系,速度会大大加快)

  • 将大部分代码放入函数中。这大大加快了CPython和PyPy的速度。而不是:

    一些代码

做:

差不多就是这样

干杯,
fijal

对于这种简单的数字脚本,您只需要做两件事:

  • 使用PyPy(它没有复杂的依赖关系,速度会大大加快)

  • 将大部分代码放入函数中。这大大加快了CPython和PyPy的速度。而不是:

    一些代码

做:

差不多就是这样

干杯,

fijal

也许更适合于?嗯,
j=j+1
语句肯定可以删除,因为
j
将立即被覆盖。这同样适用于
j=0
语句。使用
trys=int(raw\u input())
您可以在xrange(trys)中使用
而不是whileloop@EdwinDrood当前位置我的机器和ideone都这么说。虽然在您的情况下,这并不重要(测试的数量可能更适合?嗯,
j=j+1
语句肯定可以被删除,因为
j
将立即被覆盖。
j=0
语句也是如此。使用
trys=int(原始输入())
您可以在xrange(trys)中使用
for u
而不是whileloop@EdwinDrood当前位置我的机器和ideone都这么说。不过对你来说,这不重要(测试次数仍然超过时间限制
0.2s
@EdwinDrood:我无法打开你发布的链接,因为它不接受我的旧Firefox。但一般来说,在计算字符串相似性时,你会使用某种动态编程算法,例如维基百科上列出的算法。仍然超过时间限制
0.2s
@Ed。)winDrood:嗯,我不能打开你发布的链接,因为它不接受我以前的Firefox。但一般来说,在计算字符串相似性时,你会使用某种动态编程算法,例如Wikipedia上列出的。@larsmans:尝试一些简单的方法,比如:
I=0\n,而在模块级和内部,I<1000000:I+=1
一个函数。你自己看。我立刻相信了你,我只是想知道它是如何工作的:)顶级代码的编译方式是否不同?@larsmans:我想访问全局名称的速度比访问本地名称的速度慢。@larsmans:尝试一些简单的方法,例如:
I=0\n而我<1000000:I+=1
在模块级和函数内部。你自己看看。我立刻相信了你,我只是想知道这是如何工作的:)顶级代码的编译是否不同?@larsmans:我猜访问全局名称的速度比访问本地名称的速度慢。您的似乎比我的慢!我用
10000
chars进行了测试,您的大约用了8秒。我的大约是4.8秒。啊,就像我说的,它可以改进。但很难比较不同ma的时间
def main():
    some_code

if __name__ == '__main__':
    main()