1. 最长公共子串问题简介
最长公共子串(Longest Common Substring)问题是计算机科学中的一个经典问题,是字符串处理中常见的一种问题。给定两个字符串,要求从中找出最长的公共子串,即在两个字符串中连续出现的最长的子串。
最长公共子串问题与最长公共子序列问题类似,但是要求找到的子串必须是连续的。例如,对于字符串"ABABC"和"BABCA",它们的最长公共子串为"ABC"。
2. 暴力解法
最简单的方法是使用暴力解法,遍历两个字符串的所有子串,然后逐个比较它们的每个字符,找出最长的公共子串。下面是PHP代码实现:
function findLongestCommonSubstring($str1, $str2) {
$maxLen = 0;
$maxSubstr = "";
// 遍历所有子串
for ($i = 0; $i < strlen($str1); $i++) {
for ($j = 0; $j < strlen($str2); $j++) {
$len = 0;
$substr = "";
// 比较每个字符
while ($i + $len < strlen($str1) && $j + $len < strlen($str2) && $str1[$i + $len] == $str2[$j + $len]) {
$substr .= $str1[$i + $len];
$len++;
}
// 更新最长公共子串
if ($len > $maxLen) {
$maxLen = $len;
$maxSubstr = $substr;
}
}
}
return $maxSubstr;
}
$str1 = "ABABC";
$str2 = "BABCA";
echo findLongestCommonSubstring($str1, $str2); // 输出 "ABC"
3. 动态规划解法
虽然暴力解法可以找到最长公共子串,但是时间复杂度较高,不适用于较大规模的字符串。动态规划是一种常用的解决最长公共子串问题的方法。
动态规划的思想是将一个大问题拆分成多个子问题,通过解决子问题来解决原来的问题。对于最长公共子串问题,可以使用一个二维数组来记录每个子问题的结果。下面是PHP代码实现:
function findLongestCommonSubstring($str1, $str2) {
$len1 = strlen($str1);
$len2 = strlen($str2);
$maxLen = 0;
$maxEndPos = 0;
// 创建二维数组,用于记录子问题的结果
$dp = array();
for ($i = 0; $i < $len1; $i++) {
$dp[$i] = array();
for ($j = 0; $j < $len2; $j++) {
$dp[$i][$j] = 0;
}
}
// 动态规划计算最长公共子串
for ($i = 0; $i < $len1; $i++) {
for ($j = 0; $j < $len2; $j++) {
if ($str1[$i] == $str2[$j]) {
if ($i == 0 || $j == 0) {
$dp[$i][$j] = 1;
} else {
$dp[$i][$j] = $dp[$i - 1][$j - 1] + 1;
}
// 更新最长公共子串的长度和结束位置
if ($dp[$i][$j] > $maxLen) {
$maxLen = $dp[$i][$j];
$maxEndPos = $i;
}
}
}
}
return substr($str1, $maxEndPos - $maxLen + 1, $maxLen);
}
$str1 = "ABABC";
$str2 = "BABCA";
echo findLongestCommonSubstring($str1, $str2); // 输出 "ABC"
4. 总结
最长公共子串问题是计算机科学中的一个重要问题,可以通过暴力解法和动态规划解法来求解。暴力解法简单直观,但是时间复杂度较高;动态规划解法通过拆分问题的思想,通过记录子问题的结果来求解最长公共子串,时间复杂度较低。
在实际应用中,可以根据具体情况选择合适的方法来解决最长公共子串问题。对于较小规模的字符串,暴力解法即可满足需求;而对于较大规模的字符串,动态规划解法更适合。