![](/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.