LCS算法&最大公共子串&最長公共子序列 PHP 實現

求兩個字符串的最大公共子串&最長公共子序列

輸入:
abcbdab
bdcaba
4

bdcabaabcbdab 的最大公共子串長度爲 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),但是這樣依舊有空間的浪費,有些數據的存儲是不必要的,可以進一步做優化

發佈了29 篇原創文章 · 獲贊 5 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章