0012演算法筆記 動態規劃 最長公共子串問題

2021-07-25 03:56:23 字數 2855 閱讀 6633

1、問題相關定義

(1)字串:乙個字串s是將n 個字元順次排列形成的陣列, n稱為s的長度,表示為len(s) 。s的第i字元表示為s[ i ]。

(2)子串:字串s的子串s[ i:j ] ( i ≤ j)表示s串中從i到j這一段,也就是排列s[ i ] , s[ i + 1 ] , ⋯,s[ j ] 形成的字串。

(3)字尾:字尾是指從某個位置i開始到整個串末尾結束的乙個特殊子串。字串s的從i開頭的字尾表示為suffix( s,i) ,也就是suffix( s, i) = s[ i:len ( s) ]。

(4)公共字尾:字串u 如果既是字串s的字尾又是字串t的字尾,則字串u 是字串s和t的乙個公共字尾。

(5)最長公共字尾:字串s和t的最長公共字尾是指字串s和t的所有公共字尾中長度最大的子串。

(4)公共子串:字串u 如果既是字串s的子串又是字串t的子串,則字串u 是字串s和t的乙個公共子串。

(5)最長公共子串:字串s和t的最長公共子串是指字串s和t的所有公共子串中長度最大的子串。

例:給定2 個長度分別為4, 4 的字串「abab」,「baba」,它們的公共子串(common substring) 有「」,「a」,「b」,「ab」,「ba」,「aba」,「bab」。其中最長公共子串(lcs) 即為「aba」或「bab」。

2、動態規劃求解

在使用動態規劃求解2個長度分別為p, q的字串s,t的最長公共子串問題前,先給出求它們任意字首子串對s[1:i],t[1:j]的最長公共字尾的演算法,其中:1 ≤ i ≤ p,1 ≤ j ≤ q。設lcsuffix(s[1:i],t[1:j])表示字首子串對s[1: i] ,t[1:j] 的最長公共字尾,則該問題的遞推關係式如下:

例如:字串s「baba」, t「abab」, 使用上面遞推關係式求得字串s, t所有字首子串對的最長公共字尾,如下表所示:

字串s, t所有字首子串對應的最長公共字尾中長度最大的即為字串s, t的最長公共子串,即:

[cpp]view plain

copy

// cpppro.cpp : 定義控制台應用程式的入口點。

//3m6 最長公共子串,動態規劃實現

#include "stdafx.h"

#include 

#include 

using

namespace

std;   

string getlcslength(string &s, string &t);  

intmain()  

string getlcslength(string &s, string &t)  

char

char1 = 

'\0'

;  char

char2 = 

'\0'

;  int

len = 0;  

string lcs = ""

;  for

(int

i=0; i

else

else

if(num[i][j].length()>len)  

else

if(num[i][j].length()==len)  

}  }  }  

for(

inti=0;i

delete

num;  

return

lcs;  

}  

程式執行結果如下:

使用動態規劃演算法求2個長度分別為p, q的字串s, t的最長公共子串需要構造乙個二維表,該二維表含有pq個項,使用遞推的方法求每項的時間負責度為o (1) ,所以求出所有項的時間複雜度為o (pq) 。在二維表中只需找到乙個最大值項,其對應於原2個字串的最長公共子串,因此使用動態規劃演算法的時間複雜度為o (pq) 。

建立2個長度分別為p, q的字串s, t的廣義字尾陣列的時間複雜度為o (p + q) ,求廣義字尾陣列中相鄰子串的最長公共字首的時間複雜度為,即需要預處理時間複雜度為o(p + q) ,每次查詢最長公共字首的時間複雜度為o(1) 。遍歷所有最長公共字首的時間複雜度為o(p+q) ,因此使用廣義字尾陣列解決最長公共子串的時間複雜度為o(p+q) 。對於字串s, t,它的廣義字尾陣列在不降低效能同時需要使用2 (p + q) 空間。

解決2個長度分別為p, q的字串最長公共子串問題的動態規劃演算法,廣義字尾樹演算法以及廣義字尾陣列演算法在時間複雜度,空間複雜度以及程式設計實現上的比較分析總結如下表所示:

其中動態規劃演算法以及廣義字尾樹演算法的研究已經非常成熟,在計算機演算法領域有著各種各樣的應用,但在解決字串最長公共子串問題上還有一定不足,即動態規劃演算法占用的時間複雜度以及空間複雜度都很高,而廣義字尾樹演算法雖然降低了時間複雜度,但其空間複雜度還是較高,另外程式設計實現也較難。雖然廣義字尾陣列的理論研究還在發展中,但就目前的研究成果而言,在解決字串最長公共子串問題上,根據上面給出的演算法,它可以綜合動態規劃演算法以及廣義字尾樹演算法的優點,既保證了線性的時間複雜度,較低的空間複雜度又易於程式設計實現。改進的字尾陣列演算法及相關定義應用可檢視博文《最長公共子串問題的字尾陣列解法》。

動態規劃之最長公共子串行演算法

動態規劃之最長公共子串行演算法 演算法思想 假設x x1,x2,xm y static void init xy void getchar for i 1 i n i getchar static void lcs length void else if c i 1 j c i j 1 else p...

演算法 最長公共子串行(動態規劃)

給定兩個字串 text1 和 text2,返回這兩個字串的最長公共子串行的長度。乙個字串的 子串行 是指這樣乙個新的字串 它是由原字串在不改變字元的相對順序的情況下刪除某些字元 也可以不刪除任何字元 後組成的新字串。例如,ace 是 abcde 的子串行,但 aec 不是 abcde 的子串行。兩個...

演算法題9 動態規劃之最長公共子串行 最長公共子串

題目 如果字串1的所有字元按其在字串中的順序出現在另外乙個字串2中,則字串1稱之為字串2的子串行。注意,並不要求子子串行 字串1 的字元必須連續出現在字串2中。請編寫乙個函式,輸入兩個字串,求它們的最長公共子串,並列印出最長公共子串行。例如 輸入兩個字串bdcaba和abcbdab,字串bcba和b...