簡體   English   中英

我如何讓這個函數返回最長的公共子序列(不是 lcs 的長度)

[英]How do i make this function return what the Longest common subsequence(not the length of lcs)

嗨,我正在解決這個問題,我必須返回最長公共子序列(lcs)的長度,並且我能夠形成一個執行相同操作的遞歸函數,但現在我想知道如何讓這個函數返回 lcs 是什么。 例如seq1 = 'serendipitous' seq2 = 'precipitation' lcs of seq1 and seq2 is - reipito

我想制作一個返回“reipito”的函數

我寫的返回 lcs 長度的函數是

def lcs_recursive(seq1, seq2, idx1 = 0, idx2 = 0):
    
    if idx1 == len(seq1) or idx2 == len(seq2):
        return 0 
        
    if seq1[idx1] == seq2[idx2]:
        return 1 + lcs_recursive(seq1, seq2, idx1 + 1, idx2 + 1)
    
    else:
        option1 = lcs_recursive(seq1, seq2, idx1 + 1, idx2)
        option2 = lcs_recursive(seq1, seq2, idx1, idx2 + 1)
        
        return max(option1, option2)

此函數返回長度如何 lcs

我厭倦了這樣做但失敗了。 請幫忙

對您的代碼進行最少的更改:

def lcs_recursive(seq1, seq2, idx1 = 0, idx2 = 0, lcs = ''):
    
    if idx1 == len(seq1) or idx2 == len(seq2):
        return lcs
        
    if seq1[idx1] == seq2[idx2]:
        return lcs_recursive(seq1, seq2, idx1 + 1, idx2 + 1, lcs + seq1[idx1])
    
    else:
        option1 = lcs_recursive(seq1, seq2, idx1 + 1, idx2, lcs)
        option2 = lcs_recursive(seq1, seq2, idx1, idx2 + 1, lcs)
        
        return max(option1, option2, key=len)

seq1 = 'serendipitous'
seq2 = 'precipitation'
print(lcs_recursive(seq1, seq2)) # reipito

既然你可能調用lcs_recursive具有相同索引對多次, functools.cache如果使用Python> = 3.9或functools.lru_cache如果使用Python> = 3.2可以提高性能。

例如,如果seq1 = 'ab'seq2 = 'bd'lcs_recursive('ab', 'bd')最終將調用lcs_recursive('ab', 'bd', 2, 1)兩次(您可以通過在你的函數中做print(idx1, idx2)第一件事)。 使用下面的@lru_cache優化,在第一次調用(idx1=2, idx2=1) (即lcs_recursive('ab', 'bd', 2, 1) )時,結果對應於(idx1=2, idx2=1)計算並存儲(在緩存中,您可以將其視為字典)。 在對同一索引對( (idx1=2, idx2=1) )的后續調用中,將查找存儲的結果,以便不必重新計算。 通常, lru_cache會根據輸入lru_cache結果。 這就是為什么在下面的代碼中,函數helper只需要idx1idx2 - 使lru_cache更容易正常工作。

from functools import lru_cache

def lcs_recursive(seq1, seq2):
    @lru_cache
    def helper(idx1 = 0, idx2 = 0):
    
        if idx1 == len(seq1) or idx2 == len(seq2):
            return ''
            
        if seq1[idx1] == seq2[idx2]:
            return  seq1[idx1] + helper(idx1 + 1, idx2 + 1)
        
        option1 = helper(idx1 + 1, idx2)
        option2 = helper(idx1, idx2 + 1)
        
        return max(option1, option2, key=len)
    
    return helper()

seq1 = 'serendipitous'
seq2 = 'precipitation'
print(lcs_recursive(seq1, seq2)) # reipito

作為比較,使用seq1 = 'serendipitous'seq2 = 'precipitation' lcs_recursive_uncached(seq1, seq2)進行 1119564 次遞歸調用,而lcs_recursive_cached(seq1, seq2)僅進行 184 次遞歸調用:

number_of_calls_uncached = 0
def lcs_recursive_uncached(seq1, seq2, idx1 = 0, idx2 = 0, lcs = ''):
    global number_of_calls_uncached
    number_of_calls_uncached += 1

    if idx1 == len(seq1) or idx2 == len(seq2):
        return lcs
        
    if seq1[idx1] == seq2[idx2]:
        return lcs_recursive_uncached(seq1, seq2, idx1 + 1, idx2 + 1, lcs + seq1[idx1])
    
    else:
        option1 = lcs_recursive_uncached(seq1, seq2, idx1 + 1, idx2, lcs)
        option2 = lcs_recursive_uncached(seq1, seq2, idx1, idx2 + 1, lcs)
        
        return max(option1, option2, key=len)

seq1 = 'serendipitous'
seq2 = 'precipitation'
print(number_of_calls_uncached) # 0
print(lcs_recursive_uncached(seq1, seq2)) # reipito
print(number_of_calls_uncached) # 1119564


from functools import lru_cache

number_of_calls_cached = 0
def lcs_recursive_cached(seq1, seq2):
    @lru_cache
    def helper(idx1 = 0, idx2 = 0):
        global number_of_calls_cached
        number_of_calls_cached += 1

        if idx1 == len(seq1) or idx2 == len(seq2):
            return ''
            
        if seq1[idx1] == seq2[idx2]:
            return  seq1[idx1] + helper(idx1 + 1, idx2 + 1)
        
        option1 = helper(idx1 + 1, idx2)
        option2 = helper(idx1, idx2 + 1)
        
        return max(option1, option2, key=len)
    
    return helper()

seq1 = 'serendipitous'
seq2 = 'precipitation'
print(number_of_calls_cached) # 0
print(lcs_recursive_cached(seq1, seq2)) # reipito
print(number_of_calls_cached) # 184

轉換發布的代碼以返回 LCS 而不是長度。

def lcs_recursive(seq1, seq2, idx1 = 0, idx2 = 0):
    
    if idx1 == len(seq1) or idx2 == len(seq2):
        return ""
        
    if seq1[idx1] == seq2[idx2]:
        return  seq1[idx1] + lcs_recursive(seq1, seq2, idx1 + 1, idx2 + 1)
    
    else:
        option1 = lcs_recursive(seq1, seq2, idx1 + 1, idx2)
        option2 = lcs_recursive(seq1, seq2, idx1, idx2 + 1)
        
        
        return max(option1, option2, key = len)
                   
                   

測試

seq1 = 'serendipitous' 
seq2 = 'precipitation'
                   
print(lcs_recursive(seq1, seq2))
# Output: 'reipito'

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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