簡體   English   中英

最長公共子序列的界限

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM