/**
* 获取两字符串所有公共子串【连续的】 例:abc ac => a || c
*
* @param string $str1 字符串1
* @param string $str2 字符串2
*
* @return array
*/
function public_string(string $str1, string $str2): array
{
$data = []; // 容器
$arr1 = mb_str_split($str1);
$arr2 = mb_str_split($str2);
$len1 = count($arr1);
$len2 = count($arr2);
for ($i = 0; $i < $len1; ++$i) {
for ($j = 0; $j < $len2; ++$j) {
// 字符串子串起点
if ($arr1[$i] === $arr2[$j]) {
// 字符串子串【起点1 终点1 起点2 终点2 长度 相同字符串】 让他们位置分别加一,直到不一样或者结束。
$tmp = [$i, $i, $j, $j, 1, $arr1[$i]];
while (true) {
++$tmp[1];
++$tmp[3];
if (!isset($arr1[$tmp[1]]) || !isset($arr2[$tmp[3]]) || $arr1[$tmp[1]] !== $arr2[$tmp[3]])
break;
++$tmp[4];
$tmp[5] .= $arr1[$tmp[1]];
}
// 抵消while(true)里面+1,否则再次循环就+2了
--$tmp[1];
--$tmp[3];
$data[] = $tmp; // 保存子串
// 避免重复匹配
$i = $tmp[1];
$j = $tmp[3];
}
}
}
return $data;
}
/**
* 获取两字符串所有最长公共子串 注意:最长字符串子串可能有多个
*
* @param string $str1 字符串1
* @param string $str2 字符串2
*
* @return array
*/
function long_public_string(string $str1, string $str2): array
{
$data = []; // 最长公共子串容器
$l = 0; // 最长子序列长度
// 获取所有公共子串
$substring = public_string($str1, $str2);
// 找到最长公共子串长度及个数
foreach ($substring as $value) {
if ($l > $value[4]) continue;
$l = $value[4];
}
// 在所有字符串子串中找到最长的子串
foreach ($substring as $value) {
if ($l === $value[4]) $data[] = $value;
}
return $data;
}
$str1 = '安保处的';
$str2 = '安保的';
v(public_string($str1, $str2));
v(long_public_string($str1, $str2));
运行结果: