[英]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
只需要idx1
和idx2
- 使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.