src/DiffToolkit.php
public function halfMatch($text1, $text2)
    {
        if (mb_strlen($text1) > mb_strlen($text2)) {
            $longtext = $text1;
            $shorttext = $text2;
        } else {
            $shorttext = $text1;
            $longtext = $text2;
        }

        if (mb_strlen($longtext) < 4 || mb_strlen($shorttext) * 2 < mb_strlen(mb_strlen($longtext))) {
            // Pointless
            return null;
        }

        // First check if the second quarter is the seed for a half-match.
        $hm1 = $this->halfMatchI($longtext, $shorttext, (int)((mb_strlen($longtext) + 3) / 4));
        // Check again based on the third quarter.
        $hm2 = $this->halfMatchI($longtext, $shorttext, (int)((mb_strlen($longtext) + 1) / 2));

        if (empty($hm1) && empty($hm2)) {
            return null;
        } elseif (empty($hm2)) {
            $hm = $hm1;
        } elseif (empty($hm1)) {
            $hm = $hm2;
        } else {
            // Both matched.  Select the longest.
            if (mb_strlen($hm1[4] > $hm2[4])) {
                $hm = $hm1;
            } else {
                $hm = $hm2;
            }
        }

        // A half-match was found, sort out the return data.
        if (mb_strlen($text1) > mb_strlen($text2)) {
            return array($hm[0], $hm[1], $hm[2], $hm[3], $hm[4]);
        } else {
            return array($hm[2], $hm[3], $hm[0], $hm[1], $hm[4]);
        }
    }
public function halfMatch($text1, $text2)
    {
        if (mb_strlen($text1) > mb_strlen($text2)) {
            $longtext = $text1;
            $shorttext = $text2;
        } else {
            $shorttext = $text1;
            $longtext = $text2;
        }

        if (mb_strlen($longtext) < 4 || mb_strlen($shorttext) * 2 < mb_strlen(mb_strlen($longtext))) {
            // Pointless
            return null;
        }

        // First check if the second quarter is the seed for a half-match.
        $hm1 = $this->halfMatchI($longtext, $shorttext, (int)((mb_strlen($longtext) + 3) / 4));
        // Check again based on the third quarter.
        $hm2 = $this->halfMatchI($longtext, $shorttext, (int)((mb_strlen($longtext) + 1) / 2));

        if (empty($hm1) && empty($hm2)) {
            return null;
        } elseif (empty($hm2)) {
            $hm = $hm1;
        } elseif (empty($hm1)) {
            $hm = $hm2;
        } else {
            // Both matched.  Select the longest.
            if (mb_strlen($hm1[4] > $hm2[4])) {
                $hm = $hm1;
            } else {
                $hm = $hm2;
            }
        }

        // A half-match was found, sort out the return data.
        if (mb_strlen($text1) > mb_strlen($text2)) {
            return array($hm[0], $hm[1], $hm[2], $hm[3], $hm[4]);
        } else {
            return array($hm[2], $hm[3], $hm[0], $hm[1], $hm[4]);
        }
    }
Do the two texts share a substring which is at least half the length of the longer text?
This speedup can produce non-minimal diffs.

@param string $text1 First string.
@param string $text2 Second string.

@return null|array Five element array, containing the prefix of text1, the suffix of text1,
the prefix of text2, the suffix of text2 and the common middle.  Or null if there was no match.