![](/img/trans.png)
[英]Recursion showing error for finding longest common sub-sequence in python
[英]Bound of longest common sub sequence
我需要找到递归最长公共子序列问题(仅它的长度)的最紧密边界(对于最坏的情况)。 我的意思是复杂性以m和n为界,m是字符串s的长度,n是字符串t的长度。 有人可以帮我吗?
代码是:
def lcs_len_v1(s, t):
n = len(s)
m = len(t)
return lcs_len_rec(s,n,t,m)
def lcs_len_rec(s,size_s,t,size_t):
if size_s==0 or size_t==0: #if one of the strings is empty
return 0
if s[0] == t[0]: #if we find a common char
return lcs_len_rec(s[1:],len(s[1:]), t[1:],len(t[1:]))+1
else:
return max(lcs_len_rec(s,len(s),t[1:],len(t[1:])), lcs_len_rec(s[1:],len(s[1:]),t,len(t)))
这是我用Python编写的最快的实现:
def lcs(x, y):
'''returns the length of longest common subsequence of x and y.
>>> lcs('abcde','aebd')
3
'''
s_x, s_y = len(x), len(y)
if s_x>s_y:
x, y = y, x
s_x, s_y = s_y, s_x
y_previous = s_x*[0]
for y_char in y:
left_value = 0
diagonal_value = 0
n=0
for x_char in x:
up_value = y_previous[n]
if y_char==x_char:
left_value = diagonal_value+1
else:
if left_value<up_value:
left_value = up_value
diagonal_value = up_value
y_previous[n] = left_value
n+=1
return y_previous[-1]
如果您想提高性能,可以使用Cython进行编译。 它运行速度快90倍!
cimport cython
from libc.stdlib cimport malloc, free
def lcs(x, y):
cdef int s_x
cdef int s_y
s_x, s_y = len(x), len(y)
if s_x>s_y:
x, y = y, x
s_x, s_y = s_y, s_x
cdef int i
temp_y_previous = s_x*[0]
cdef int *y_previous
y_previous = <int *>malloc(s_x*cython.sizeof(int))
if y_previous is NULL:
raise MemoryError()
for i in xrange(s_x):
y_previous[i] = temp_y_previous[i]
cdef char *cx
cx = <char *>malloc(s_x*cython.sizeof(char))
if cx is NULL:
raise MemoryError()
i=0
for character in x:
cx[i]=ord(character)
i+=1
cdef char *cy
cy = <char *>malloc(s_y*cython.sizeof(char))
if cy is NULL:
raise MemoryError()
i=0
for character in y:
cy[i]=ord(character)
i+=1
cdef int k=0
cdef int left_value
cdef int diagonal_value
cdef int n
cdef str y_char
cdef str x_char
while k<s_y:
left_value = 0
diagonal_value = 0
n=0
while n<s_x:
if cy[k]==cx[n]:
left_value = diagonal_value+1
else:
if left_value<y_previous[n]:
left_value = y_previous[n]
diagonal_value = y_previous[n]
y_previous[n] = left_value
n+=1
k+=1
with nogil:
free(y_previous)
free(cx)
free(cy)
return y_previous[s_x-1]
我认为这会奏效。 但我也认为长弦很慢。
def max_common_str_len(s, t):
if len(s) > len(t):
return max_common_str_len(t, s)
for length in range(len(s),0,-1):
for offset in range(len(s)-length+1):
if s[offset:offset+length] in t:
return length
else:
return 0
max_common_str_len('there is a house in new orleans', 'this is a house')
产量
11
编辑
我还试验了你的代码。 我认为它对于中等字符串来说很慢,因为你的函数使用相同的参数调用lcs_len_rec
。 考虑使用装饰器缓存/记忆它:
import functools
@functools.lru_cache(maxsize=None)
def lcs_len_rec(###your code###
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.