Квест → Как хакнуть форму
Прошли: 77
В этом уроке я покажу вам, как можно использовать две малоизвестные функции PHP (metaphone($str) и levenshtein($str1, $str2)) для поиска созвучных слов на PHP. Поставив эти функции, вы получите исключительные результаты при сопоставлении фраз - для поиска орфографических ошибок или просто для нахождения фраз, звучащих одинаково.
Если вам просто нужен код, можете скачать класс из репозитория на GitHub
Функция metaphone() основана на алгоритме, который был опубликован Лоренсом Филлипсом в 1990 году в журнале Computer Language Magazine и используется для "оценки" того, как звучит английское слово. Например, для слова "Javascript" metaphone вернет строку JFSKRPT.
Функция levenshtein возвращает минимальное количество символов, которые должны быть изменены в первой строке, чтобы сравнить ее со второй. Например, строка "javacrript" должна быть изменена дважды, чтоб соответствовать строке "javascript", levenstein('javacrript', 'javascript') вернет int(2)
Вот класс SoundsLike, делающий metaphone для каждой фразы и после levenstein для каждого варианта, чтобы получить наиболее похожую строку.
class SoundsLike { private $searchAgainst = array(); private $input; /** *@param $searchAgainst - an array of strings to match against $input *@param $input - the string for which the class finds the closest match in $searchAgainst */ public function __construct($searchAgainst, $input) { $this->searchAgainst = $searchAgainst; $this->input = $input; } /** *@param $phrase - string *@return an array of metaphones for each word in a string */ private function getMetaPhone($phrase) { $metaphones = array(); $words = str_word_count($phrase, 1); foreach ($words as $word) { $metaphones[] = metaphone($word); } return $metaphones; } /** *@return the closest matching string found in $this->searchAgainst when compared to $this->input */ public function findBestMatch() { $foundbestmatch = -1; //get the metaphone equivalent for the input phrase $tempInput = implode(' ', $this->getMetaPhone($this->input)); foreach ($this->searchAgainst as $phrase) { //get the metaphone equivalent for each phrase were searching against $tempSearchAgainst = implode(' ', $this->getMetaPhone($phrase)); $similarity = levenshtein($tempInput, $tempSearchAgainst); if ($similarity == 0) // we found an exact match { $closest = $phrase; $foundbestmatch = 0; break; } if ($similarity <= $foundbestmatch || $foundbestmatch < 0) { $closest = $phrase; $foundbestmatch = $similarity; } } return $closest; } } ?>
Чтобы потестировать этот класс, используйте следующий код:
$input = "The quick brown fox jumped over the lazy dog"; // The Metaphone will be: "0 KK BRN FKS JMPT OFR 0 LS TK" $searchAgainst = array("The quick brown cat jumped over the lazy dog","Thors hammer jumped over the lazy dog", "The quick brown fax jumped over the lazy dog"); // Metaphones will be: "0 KK BRN KT JMPT OFR 0 LS TK", "0RS HMR JMPT OFR 0 LS TK", "0 KK BRN FKS JMPT OFR 0 LS TK" $SoundsLike = new SoundsLike($searchAgainst, $input); echo $SoundsLike->findBestMatch();
жаль, что для русского языка нет настолько же хорошей реализации, может, вы станете тем, кто захочет реализовать такой алгоритм? ;-)