如何加速Python字符串匹配代码

时间:2013-06-29 15:26:13

标签: python performance algorithm dynamic-programming lcs

我有这个代码来计算随机字符串之间的Longest Common Subsequence,以查看一个人可以如何准确地重建输入的未知区域。为了得到好的统计数据,我需要多次迭代它,但我目前的python实现太慢了。即使使用pypy,它目前也需要21秒才能运行一次,理想情况下我想要运行它几次。

#!/usr/bin/python

import random
import itertools
#test to see how many different unknowns are compatible with a set of LCS answers.
def lcs(x, y):
    n = len(x)
    m = len(y)
#    table is the dynamic programming table
    table = [list(itertools.repeat(0, n+1)) for _ in xrange(m+1)]
    for i in range(n+1):     # i=0,1,...,n
        for j in range(m+1):  # j=0,1,...,m
            if i == 0 or j == 0:
                table[i][j] = 0
            elif x[i-1] == y[j-1]:
                table[i][j] = table[i-1][j-1] + 1
            else:
                table[i][j] = max(table[i-1][j], table[i][j-1])

    # Now, table[n, m] is the length of LCS of x and y.
    return table[n][m]

def lcses(pattern, text):
    return [lcs(pattern, text[i:i+2*l]) for i in xrange(0,l)]

l = 15
#Create the pattern
pattern = [random.choice('01') for i in xrange(2*l)]

#create text start and end and unknown. 
start = [random.choice('01') for i in xrange(l)]
end = [random.choice('01') for i in xrange(l)]
unknown = [random.choice('01') for i in xrange(l)]

lcslist= lcses(pattern, start+unknown+end)

count = 0
for test in itertools.product('01',repeat = l):
    test=list(test)
    testlist = lcses(pattern, start+test+end)
    if (testlist == lcslist):
        count += 1

print count

我尝试将它转换为numpy,但我必须做得很糟糕,因为它实际上运行得更慢。这个代码能以某种方式加速吗?

更新。在下面发表评论后,如果lcses直接使用了一次重复会更好,这会在patterntext的所有子列表之间产生LCS长度相同。有可能以某种方式修改经典动态编程LCS算法吗?

1 个答案:

答案 0 :(得分:1)

每次调用table时,重复计算表lcses()将被重新计算15次,因为m仅依赖于nm 2*l n3*l的最大值最多为table = None def use_lcs_table(m, n, l): global table if table is None: table = lcs(2*l, 3*l) return table[m][n]

如果您的程序只计算一次表,那么它将是当前不是的动态编程。这个Python的习语就是

lcs()

除了使用类实例之外,它比全局表声明更清晰,更具可扩展性。但这让你知道为什么花了这么多时间。

在回复评论时添加:

动态编程是一种优化,需要在更短的时间内权衡额外的空间。在您的示例中,您似乎正在{{1}}中进行表预计算,但是您在每次调用时都会构建整个列表,然后将其丢弃。我并不是要求你理解你想要实现的算法,而是你编写它的方式,它可以:

  1. 没有递归关系,因此没有DP优化的理由,或
  2. 有一个递归关系,你实施的那个拙劣。