LIS最長公共子串行(動態規劃與遞迴的解法博弈)

2021-08-29 04:07:35 字數 3695 閱讀 2991

考慮假如有如下兩個字串 求其最長的公共子串行

frame

family

根據最長公共子串行的定義,顯然一眼可以看出最長子串為: fam

那麼要怎麼麼求呢?怎麼用**實現呢?

在這裡首先分析一下求法。

比如給字串乙個序號乙個串叫a串(frame),乙個叫b串(family)

a串:

| f | r | a | m | e |

b串:| f | a | m | i | l | y |

首先可以考慮採用遞迴來解決step1: 考慮首字元f相等, 那麼可以去掉f子串行長度加一

然後問題就變成了求a串(rame),b串(amily)最長子串問題。

a串:

| r | a | m | e |

b串:| a | m | i | l | y |

step2: 那如果不相等呢?

一種方法是繼續求a串和b串。(這裡顯然是不行的, 因為繼續求得結果還是不相等)另一種方法就是:去掉a串與b串不相等的首字母(r)

使得問題變為:

a串:

| a | m | e |

b串:| a | m | i | l | y |

還一種方法就是:去掉b串與a串不相等的首字母(a)

使得問題變為:

a串:

| r | a | m | e |

b串:| m | i | l | y |

一眼看去並不知道2和3哪種方法求出的結果更好。於是取其中最大的那個,即為所求。

那到這裡問題分析完了, 給**吧!

/*

* 最長公共子串行

*/public

class

test_1

if(a.

charat(0

)== b.

charat(0

))else

}public

static

void

main

(string[

] args)

}

遞迴時間複雜度

從**中不難發現此遞迴的時間複雜度非常的高。近似於2的n次方

而時間複雜度主要**在於這一行**。

return math.

max(最長公共子串行_遞迴(a, b.

substring(1

)), 最長公共子串行_遞迴(a.

substring(1

), b)

);

我們知道2的n次方是乙個**性數量級。當a串和b串長度達到10幾可能就需要好幾秒才能求出。

那有沒有一種更好的方法呢?

其實你再分析上面考慮的幾種情況。

當字元相等時

當字元不相等時

假如將兩個字串分別放在一張圖的x軸和y軸上。

當字元相等時剪下a和b時所得的結果(也就是左上角 + 1)即可。

當字元不相等時, 取分別減掉a和減掉b的結果的最大值(左邊 和 上邊最大值)即可。

於是可以初始化矩陣為:

思想解決了,那麼**就很簡單了。

上**吧!

// 注: 這裡就不再寫主函式了, 此函式可以直接呼叫執行

/** * 求最長公共子串行 - 動態規劃演算法

* @param str1 a串

* @param str2 b串

* @return

*/public

static

intlcs

(string str1, string str2)

else

else}}

}/ 計算結束

// 輸出路徑矩陣

system.out.

println

("路徑矩陣d為: ");

for(

int i =

0; i < str1len +

1; i++

) system.out.

println()

;}// 輸出最長子串// 通過路徑矩陣可以逆向找出最長子序列是哪幾個字元構成的

int tfind =10;

int i = str1len;

int j = str2len;

stringbuffer lscstr =

newstringbuffer(""

);while

(tfind !=0)

else

if(tfind ==2)

else

if(tfind ==1)

}// 輸出最長序列// 由於是逆向構造出的, 所以要翻轉一下字串

system.out.

println

("最大子串行為: "

+ lscstr.

reverse()

);system.out.

println

("最大子串行長度為: "

+ mymap[str1len]

[str2len]);

// 返回最大子串行長度

return mymap[str1len]

[str2len]

;}

動態規劃時間複雜度

從**中不難發現動態規劃的時間複雜度相較與遞迴減小了很多。

近似於n*m(n為a串長度, m為b串長度)

而時間複雜度主要**在於這兩行**。

for

(int i =

1; i < str1len +

1; i++){

for(

int j =

1; j < str2len +

1; j++

){

空間複雜度

n*m(用了兩個二維陣列來存放路徑**和結構矩陣。)

不難看出動態規劃能夠較好的解決這一問題。

最長公共子串行 動態規劃

經常會遇到複雜問題不能簡單地分解成幾個子問題,而會分解出一系列的子問題。簡單地採用把大問題分解成子問題,並綜合子問題的解匯出大問題的解的方法,問題求解耗時會按問題規模呈冪級數增加。為了節約重複求相同子問題的時間,引入乙個陣列,不管它們是否對最終解有用,把所有子問題的解存於該陣列中,這就是動態規劃法所...

最長公共子串行 動態規劃

關於用動態規劃法求兩個序列的最長公共子串行問題的相關知識見 王曉東 計算機演算法設計與分析 第三章。注意,這裡所指的最長公共子串行是可以不相鄰的,與平常所說的最長公共子串 相鄰的 不一樣。直接上 lcs.h ifndef lcs h define lcs h class lcstring endif...

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

定義 乙個數列 如果分別是兩個或多個已知數列的子串行,且是所有符合此條件序列中最長的,則 稱為已知序列的最長公共子串行。考慮最長公共子串行問題如何分解成子問題,設a a0,a1,am 1 b b0,b1,bm 1 並z z0,z1,zk 1 為它們的最長公共子串行。不難證明有以下性質 1 如果am ...