За основу взят алгоритм реализованный на языке Pyton и опубликованный в статье Алгоритм Шинглов – поиск нечетких дубликатов текста
<? class Shingler { var $length; var $stopSymbols = array(".",",","!","?",":",";","-","n","r","(",")"); var $stopWords = array('это', 'как', 'так', 'и', 'в', 'над', 'к', 'до', 'не', 'на', 'но', 'за', 'то', 'с', 'ли', 'а', 'во', 'от', 'со', 'для', 'о', 'же', 'ну', 'вы', 'бы', 'что', 'кто', 'он', 'она'); function Shingler($length, $stopSymbols = false, $stopWords = false) { $this->length = $length; if ($stopSymbols != false) $this->stopSymbols = $stopSymbols; if ($stopWords != false) $this->stopWords = $stopWords; } function setStopWords($stopWords) { $this->stopWords = $stopWords; } function getStopWords() { return $this->stopWords; } function setStopSymbols($stopSymbols) { $this->stopSymbols = $stopSymbols; } function getStopSymbols() { return $this->stopSymbols; } function compare($textA, $textB) { $shinglesA = $this->shingle($this->canonize($textA)); $shinglesB = $this->shingle($this->canonize($textB)); $matches = 0; foreach ($shinglesA as $shingle) { if (in_array($shingle, $shinglesB)) $matches++; } return 2 * 100 * $matches / (count($shinglesA) + count($shinglesB)); } function canonize($text) { $text = str_replace($this->stopSymbols, null, $text); $text = strtolower(eregi_replace(" +", " ", $text)); $words = explode(" ", $text); foreach ($words as $i => $word) { if (in_array(strtolower($word), $this->stopWords)) $words = array_remove($word, $words); } return implode(" ", $words); } function shingle($text) { $result = array(); $words = explode(" ", $text); for ($i = 0; $i <= count($words) - $this->length; $i++) { $currentShingle = array(); for ($j = 0; $j < $this->length; $j++) { array_push($currentShingle, $words[$i + $j]); } $shingledText = implode(" ", $currentShingle); array_push($result, crc32($shingledText)); } return $result; } } function array_remove($val, &$arr) { $result = $arr; for ( $x = 0; $x < count($result); $x++) { $i = array_search($val, $result); if (is_numeric($i)) { $left = array_slice($result, 0, $i); $right = array_slice($result, $i + 1, count($result) - 1); $result = array_merge($left, $right); } } return $result; } ?>
Пример использования:
<? $textA = "Разум дан для того, чтобы он разумно жил, а не для того только, чтобы он понимал, что он неразумно живет."; $textB = "Разум дан человеку для того, чтобы он разумно жил, а не для того только, чтобы он понимал, что он неразумно живет."; require_once("shingler.php"); $shingler = new Shingler(10); echo $shingler->compare($textA, $textB); ?>