考慮假如有如下兩個字串 求其最長的公共子串行
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 ...