1. 程式人生 > 其它 >演算法題(5)最長公共子串

演算法題(5)最長公共子串

技術標籤:演算法題部落格

最長公共子串

問題描述: 給定兩個不為空的字串,求這兩個字串之間最長的公共子串。

思路: 我們藉助動態規劃的思想,利用遞推公式起始向後逐步計算兩個字串的部分最長公共子串,直至得出整體的最大子串。遞推公式如下:
f ( i , j ) = { 0 A [ i ] ≠ B [ j ] ∩ ( i = 0 ∪ j = 0 ) 1 A [ i ] = B [ j ] ∩ ( i = 0 ∪ j = 0 ) 0 A [ i ] ≠ B [ j ] f ( i − 1 , j − 1 ) + 1 A [ i ] = B [ j ] f(i,j)=\begin{cases} 0 & \text A[i]\not=B[j]\cap (i=0 \ \cup \ j = 0)\\1 & \text A[i]=B[j]\cap (i=0 \ \cup \ j = 0)\\0 & \text A[i]\not=B[j]\\ f(i-1, j-1) +1 & \text A[i]=B[j] \end{cases}

f(i,j)=010f(i1,j1)+1A[i]=B[j](i=0j=0)A[i]=B[j](i=0j=0)A[i]=B[j]A[i]=B[j]

  同levenshtein編輯距離演算法類似,最長公共子串同樣需要填充表格來列舉所有位置的編輯距離,從而找出最大值。下面我們給出實現程式碼:


class solution:

    def __init__(self, A, B):
        self.A = A
        self.B = B
        self.Matrix = []
        self.lcstring(self.A,
self.B) def lcstring(self, A, B): lengthA = len(A) lengthB = len(B) longest = 0 longestend = [] if lengthA == 0 or lengthB == 0 : return for i in range(lengthA): self.Matrix.append([]) for j in range(lengthB): if
A[i] == B[j] : if i == 0 or j == 0: self.Matrix[i].append(1) else: self.Matrix[i].append(self.Matrix[i-1][j-1]+1) if self.Matrix[i][j] > longest: longestend.clear() longest = self.Matrix[i][j] longestend.append(i) continue if self.Matrix[i][j] == longest: longestend.append(i) else: self.Matrix[i].append(0) print(longest) for i in longestend: print(A[i-(longest-1):i+1]) if __name__ == '__main__': sol = solution("helloworld","loop")

  上述程式碼輸出為最長公共子串的長度,以及該長度的所有子串集。執行結果如下:

在這裡插入圖片描述
  我們將輸入字串稍作修改(”helloworld“改為“hilloworld”,“loop”改為“iloor”),以測試其能否完全輸出所有子串,輸出結果如下:
在這裡插入圖片描述
  輸出結果表明,我們的演算法基本正確,讀者可以嘗試使用。