【问题标题】:How can I optimize this Python code to run faster?如何优化此 Python 代码以更快地运行?
【发布时间】:2012-01-05 09:36:21
【问题描述】:

我正在解决一个有时间和内存限制的问题,不幸的是,这没有达到时间限制。

我对 Python 还很陌生,因此我们非常感谢任何有关更快/更好方法的反馈。

这是程序试图解决的问题:

将两个字符串 A 和 B 的相似度定义为它们共享的最长公共前缀的长度。即AAAB和AABCAAAB的相似度为2。

程序应输出输入字符串及其所有后缀的相似度总和。即对于 AAAB,它应该输出

相似度(AAAB,AAAB) + 相似度(AAAB,AAB) + 相似度(AAAB,AB) +相似度(AAAB,B) = 4 + 2 + 1 + 0 = 7

输入的第一行是要输入的字符串个数,后面的每一行都包含一个要处理的字符串。

from array import array

n = int(sys.stdin.readline()) 
A = [0] * n #List of answers

for i in range(1,n+1):
  string = sys.stdin.readline().strip()    
  A[i-1] = len(string)
  for j in range(1, len(string)):
    substr = string[j:len(string)]
    sum = 0
    for k in range(0, len(substr)):
        if substr[k] != string[k]:
            break
        else:
            sum += 1
    A[i-1] += sum

for i,d in enumerate(A):
  print d

【问题讨论】:

  • 如果您使用的是 python 2.x,您可以首先将所有这些 range 更改为 xrange。有什么好的理由需要逐行而不是一大块地从输入中读取?
  • 顺便说一句,真正的问题是摆脱三重嵌套循环。我相信你可以用一些聪明的逻辑重新实现它!
  • 你应该寻找更快的算法。
  • 这是一个很小的问题,但仍然如此。循环中有 3 个“len(string)”。我认为使用“len_string=len(string)”计算一次并稍后使用 len_string 可以节省 len() 函数的 2 次计算。或者 Python 会自动执行,有人知道吗?
  • 我怀疑 Python 会自动执行此操作,因为 len(string) 可能会在两次调用之间发生变化(尽管在这种情况下不会)。

标签: python performance optimization


【解决方案1】:

在性能方面更喜欢 xrange,因为它在 python2.X 中的迭代速度更快但我能给出的最佳建议是使用timeit 来衡量更改和改进,同时调整你的算法。

在这里搜索了另一个实现:Longest Common substring 解决方案,但 python-Levenshtein 库可能是您最好的选择,因为它具有 C 扩展以提高速度...

【讨论】:

  • 现在想来,核心算法本身可以改进很多,所以我会继续努力。次要修复(xrange,逐行读取输入)不足。这不完全是最长公共子串问题,但它很接近,我将应用类似的想法,所以我会接受这个答案。
【解决方案2】:

第一步是减少您正在执行的索引数量:

import sys

n = int(sys.stdin.readline())

for i in range(n):
    string = sys.stdin.readline().strip()
    sum = 0
    for offset in range(len(string)):
        suffix = string[offset:]
        for c1, c2 in zip(string, suffix):
            if c1 != c2:
                break
            sum += 1
    print sum

不过,这仍然是 O(N^2)。对于O(N),使用后缀树或数组,如http://code.google.com/p/pysuffix/

【讨论】:

    【解决方案3】:

    您可以尝试另一种实现方式

    sum(len(os.path.commonprefix([instr,instr[i:]])) for i in xrange(0,len(instr)))
    

    instr = 你所说的字符串

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-05
      • 2016-02-27
      • 1970-01-01
      相关资源
      最近更新 更多