* 动态规划
<?php
/**
* Created by PhpStorm.
* User: Mch
* Date: 8/10/18
* Time: 00:16
*/
class Solution {
/**
* 给定2个字符串$str1, $str2, 返回2个字符串的最长公共子序列
* $str1 = "1A2C3D4B56", $str2 = "B1D23CA45B6A"
* "123456"或者"12C4B6"都是最长公共子序列
* @return int[][]
*/
private static function getdp(string $str1, string $str2) {
$n1 = strlen($str1);
$n2 = strlen($str2);
$dp = new SplFixedArray($n1);
for ($i = 0; $i < $dp->getSize(); $i++) {
$dp->offsetSet($i, new SplFixedArray($n2));
}
$dp[0][0] = $str1[0]===$str2[0] ? 1 : 0;
for ($i = 1; $i < $n1; $i++) {
$dp[$i][0] = max($dp[$i-1][0], $str1[$i]===$str2[0] ? 1:0);
}
for ($j = 1; $j < $n2; $j++) {
$dp[0][$j] = max($dp[0][$j-1], $str1[0]===$str2[$j]?1:0);
}
for ($i = 1; $i < $n1; $i++) {
for ($j = 1; $j < $n2; $j++) {
$dp[$i][$j] = max($dp[$i-1][$j], $dp[$i][$j-1]);
if ($str1[$i]===$str2[$j]) {
$dp[$i][$j] = max($dp[$i][$j], $dp[$i-1][$j-1]+1);
}
}
}
return $dp;
}
public static function lcse(string $str1, string $str2) {
if (is_null($str1) || is_null($str2) || strlen($str1)===0 || strlen($str2)===0) {
return "";
}
$dp = self::getdp($str1, $str2);
$m = strlen($str1)-1;
$n = strlen($str2)-1;
$res = new SplFixedArray($dp[$m][$n]);
$index = $res->getSize()-1;
while ($index >= 0) {
if ($n > 0 && $dp[$m][$n]=== $dp[$m][$n-1]) {
$n--;
} else if ($m>0 && $dp[$m][$n]=== $dp[$m-1][$n]) {
$m--;
} else {
$res[$index--] = $str1[$m];
$m--;
$n--;
}
}
return array_reduce($res->toArray(), function($carry, $item) {
$carry .= $item;
return $carry;
}, "");
}
}
$str1 = "1A2C3D4B56";
$str2 = "B1D23CA45B6A";
echo Solution::lcse($str1, $str2).PHP_EOL; // "123456"