求兩個字符串的最大公共子串&最長公共子序列
輸入:
abcbdab
bdcaba
4
即
bdcaba
與abcbdab
的最大公共子串長度爲 4
常規思路
枚舉法,算出兩個字符串的所有子序列,然後分別作比較,選出最大的一個子串
缺點:對於一個長度爲 n 的字符串,子串個數有 2 的 n 次方個,然後在依次比較兩個字符串的子串,效率過低
動態規劃 LCS算法
以動態規劃的思想來解這個題,我們用一個二位數組 $dp[][]
來存儲各個字符串對應的狀態,具體什麼含義就不細說了,百度一下,你就知道,主要是用 PHP 實現一下
代碼如下:
function lcs($str1, $str2)
{
// 存儲生成的二維矩陣
$dp = array();
// 最大子串長度
$max = 0;
for ($i = 0; $i < strlen($str1); $i++) {
for ($j = 0; $j < strlen($str2); $j++) {
if ($str1[$i] == $str2[$j]) {
$dp[$i][$j] = isset($dp[$i-1][$j-1]) ? $dp[$i-1][$j-1] + 1 : 1;
} else {
$dp[$i-1][$j] = isset($dp[$i-1][$j]) ? $dp[$i-1][$j] : 0;
$dp[$i][$j-1] = isset($dp[$i][$j-1]) ? $dp[$i][$j-1] : 0;
$dp[$i][$j] = $dp[$i-1][$j] > $dp[$i][$j-1] ? $dp[$i-1][$j] : $dp[$i][$j-1];
}
$max = $dp[$i][$j] > $max ? $dp[$i][$j] : $max;
}
}
for ($i = 0; $i < strlen($str1); $i++) {
for ($j = 0; $j < strlen($str2); $j++) {
echo $dp[$i][$j] . " ";
}
echo "<br />";
}
var_dump($max);
}
lcs("abcbdab", "bdcaba");
對應輸出:
0 0 0 1 1 1
1 1 1 1 2 2
1 1 2 2 2 2
1 1 2 2 3 3
1 2 2 2 3 3
1 2 2 3 3 4
1 2 2 3 4 4
int 4
結論:通過動態規劃,我們使時間複雜度降爲了 O(nm),但是這樣依舊有空間的浪費,有些數據的存儲是不必要的,可以進一步做優化