public function difference(string $from, string $to): string
    {
        $flags = PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY;
        $from = preg_split('/(\W+)/u', $from, -1, $flags);
        $to = preg_split('/(\W+)/u', $to, -1, $flags);

        $matcher = new DifferenceSequenceMatcher($from, $to);
        $diff = '';

        foreach ($matcher->getOpcodes() as $opcode) {
            list($tag, $i1, $i2, $j1, $j2) = $opcode;

            if ($tag === 'equal') {
                $diff .= implode(array_slice($from, $i1, $i2 - $i1));
            } else {
                if ($tag === 'replace' || $tag === 'delete') {
                    $diff .=
                        $this->removeStart .
                        implode(array_slice($from, $i1, $i2 - $i1)) .
                        $this->removeEnd;
                }

                if ($tag === 'replace' || $tag === 'insert') {
                    $diff .=
                        $this->addStart .
                        implode(array_slice($to, $j1, $j2 - $j1)) .
                        $this->addEnd;
                }
            }
        }

        return $diff;
    }