Skip to content

Instantly share code, notes, and snippets.

@relaxnow
Created October 10, 2011 20:53
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save relaxnow/1276502 to your computer and use it in GitHub Desktop.
Save relaxnow/1276502 to your computer and use it in GitHub Desktop.
Longest Common Substring algorithm in PHP
<?php
function getLongestCommonSubstring($first, $second)
{
$longestCommonSubstringIndexInFirst = 0;
$table = array();
$largestFound = 0;
$firstLength = strlen($first);
$secondLength = strlen($second);
for ($i = 0; $i < $firstLength; $i++) {
for ($j = 0; $j < $secondLength; $j++) {
if ($first[$i] === $second[$j]) {
if (!isset($table[$i])) {
$table[$i] = array();
}
if ($i > 0 && $j > 0 && isset($table[$i-1][$j-1])) {
$table[$i][$j] = $table[$i-1][$j-1] + 1;
}
else {
$table[$i][$j] = 1;
}
if ($table[$i][$j] > $largestFound) {
$largestFound = $table[$i][$j];
$longestCommonSubstringIndexInFirst = $i - $largestFound + 1;
}
}
}
}
if ($largestFound === 0) {
return "";
}
else {
return substr($first, $longestCommonSubstringIndexInFirst, $largestFound);
}
}
echo getLongestCommonSubstring("aab", "baa") . PHP_EOL; // returns "aa"
@legale
Copy link

legale commented Nov 19, 2018

This one is about 30% faster.

function lcs2($first, $second)
{
    $len1 = strlen($first);
    $len2 = strlen($second);

    if ($len1 < $len2) {
        $shortest = $first;
        $longest = $second;
        $len_shortest = $len1;
    } else {
        $shortest = $second;
        $longest = $first;
        $len_shortest = $len2;
    }
    
    //check max len
    $pos = strpos($longest, $shortest);
    if($pos !== false) return $shortest;

    for ($i = 1, $j = $len_shortest - 1; $j > 0; --$j, ++$i) {
        for($k = 0; $k <= $i; ++$k){
            $substr = substr($shortest, $k, $j);
            $pos = strpos($longest, $substr);
            if($pos !== false) return $substr;
        }
    }

    return "";
}

@legale
Copy link

legale commented Dec 7, 2018

multibyte variant

function lcs2($first, $second)
{
    $len1 = strlen($first);
    $len2 = strlen($second);

    if ($len1 < $len2) {
        $shortest = $first;
        $longest = $second;
        $len_shortest = $len1;
    } else {
        $shortest = $second;
        $longest = $first;
        $len_shortest = $len2;
    }

    //check max len
    $pos = strpos($longest, $shortest);
    if($pos !== false) return $shortest;

    for ($i = 1, $j = $len_shortest - 1; $j > 0; --$j, ++$i) {
        for($k = 0; $k <= $i; ++$k){
            $substr = substr($shortest, $k, $j);
            $pos = strpos($longest, $substr);
            //if found then check last char if it is > 128 then trim it
            if($pos !== false) return ord($substr[$j-1]) > 128 ? substr($substr, 0, $j - 1) : $substr;
        }
    }

    return "";
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment