PHP

Проверка похожести двух слов

Точное сравнение двух символьных строк, даже регистронезависимое, выполнить нетрудно. А как быть, если в одной их них встречаются символы другого алфавита, похожие по написанию? Так, буква "E" в русской и английской раскладке имеет одинаковое написание, или вместо русской "Н(н)" можно написать английскую "H(h)". Этим могут воспользоваться всякие ублюдки, например оставить сообщение на форуме якобы от администрации, зарегистрировав ник, внешне похожий на ник одного из админов. Для проверки похожести двух строк я использую следующую функцию:
// -----------------------------------------------------
// Функция проверки похожести двух слов
// Параметры: $name1 и $name2 - слова для проверки
// $register = TRUE - проверка регистронезависима
//           = FALSE - проверка с учетом регистра
// На выходе: TRUE - слова похожи, FALSE - отличаются
// -----------------------------------------------------
function chk_similarity($word1, $word2, $register=false) {
  // Очистить слова от служебных символов
  $word1=eregi_replace("[^0-9a-zа-я]","",$word1);
  $word2=eregi_replace("[^0-9a-zа-я]","",$word2);
 
  // Возврат FALSE если длина слов различается
  // или хотя бы одно из них пустое
  if ((strlen($word1)!==strlen($word2)) || strlen($word1)*strlen($word2)==0) {
    return false;
  }
 
  // Заполнить таблицу соответствий
  $pattern1="";
  $pattern2=Array();
 
  $pattern1.="aа";
  $pattern2[]="[аa]";
  $pattern2[]="[аa]";
 
  $pattern1.="AА";
  $pattern2[]="[АA]";
  $pattern2[]="[АA]";
 
  $pattern1.="BВ";
  $pattern2[]="[BВ]";
  $pattern2[]="[BВ]";
 
  $pattern1.="bь";
  $pattern2[]="[bь]";
  $pattern2[]="[bь]";
 
  $pattern1.="cс";
  $pattern2[]="[cс]";
  $pattern2[]="[cс]";
 
  $pattern1.="CС";
  $pattern2[]="[CС]";
  $pattern2[]="[CС]";
 
  $pattern1.="eе";
  $pattern2[]="[eе]";
  $pattern2[]="[eе]";
 
  $pattern1.="EЕ";
  $pattern2[]="[EЕ]";
  $pattern2[]="[EЕ]";
 
  $pattern1.="HН";
  $pattern2[]="[HН]";
  $pattern2[]="[HН]";
 
  $pattern1.="iI1l";
  $pattern2[]="[iI1l]";
  $pattern2[]="[iI1l]";
  $pattern2[]="[iI1l]";
  $pattern2[]="[iI1l]";
 
  $pattern1.="kк";
  $pattern2[]="[kк]";
  $pattern2[]="[kк]";
 
  $pattern1.="KК";
  $pattern2[]="[KК]";
  $pattern2[]="[KК]";
 
  $pattern1.="MМ";
  $pattern2[]="[MМ]";
  $pattern2[]="[MМ]";
 
  $pattern1.="nп";
  $pattern2[]="[nп]";
  $pattern2[]="[nп]";
 
  $pattern1.="oо0";
  $pattern2[]="[oо0]";
  $pattern2[]="[oо0]";
  $pattern2[]="[oо0]";
 
  $pattern1.="OО0";
  $pattern2[]="[OО0]";
  $pattern2[]="[OО0]";
  $pattern2[]="[OО0]";
 
  $pattern1.="pр";
  $pattern2[]="[pр]";
  $pattern2[]="[pр]";
 
  $pattern1.="PР";
  $pattern2[]="[PР]";
  $pattern2[]="[PР]";
 
  $pattern1.="rг";
  $pattern2[]="[rг]";
  $pattern2[]="[rг]";
 
  $pattern1.="TТ";
  $pattern2[]="[TТ]";
  $pattern2[]="[TТ]";
 
  $pattern1.="uи";
  $pattern2[]="[uи]";
  $pattern2[]="[uи]";
 
  $pattern1.="xх";
  $pattern2[]="[xх]";
  $pattern2[]="[xх]";
 
  $pattern1.="XХ";
  $pattern2[]="[XХ]";
  $pattern2[]="[XХ]";
 
  $pattern1.="yу";
  $pattern2[]="[yу]";
  $pattern2[]="[yу]";
 
  $pattern1.="YУ";
  $pattern2[]="[YУ]";
  $pattern2[]="[YУ]";
 
  $pattern1.="З3";
  $pattern2[]="[З3]";
  $pattern2[]="[З3]";
 
  $pattern1.="ч4";
  $pattern2[]="[ч4]";
  $pattern2[]="[ч4]";
 
  $pattern1.="Ч4";
  $pattern2[]="[Ч4]";
  $pattern2[]="[Ч4]";
 
  // Составить регулярное выражение для проверки
  $tmp="^";
  for ($i=0; $i<strlen($word1); $i++) {
    $letter=$word1[$i];
    $pos=strpos($pattern1,$letter);
    if ($pos===false) {
      $tmp.=$letter;
    }
    else {
      $tmp.=$pattern2[$pos];
    }
  }
  $tmp.="$";
 
  // Возврат TRUE - слова похожи или равны
  // FALSE - слова отличаются
  return($register?eregi($tmp,$word2):ereg($tmp,$word2));
}

Примеры использования:
$admin_name="ManHunter";   // Ник администратора
 
$chk_name="МаnНuntеr";     // Буквы "М", "Н" и "е" в русской раскладке
chk_similarity($admin_name, $chk_name);     // --> TRUE
 
$chk_name="manhunter";     // Буквы в нижнем регистре
chk_similarity($admin_name, $chk_name);     // --> FALSE
chk_similarity($admin_name, $chk_name, 1);  // --> TRUE
 
$chk_name="[Man_Hunter]";  // Использованы служебные символы
chk_similarity($admin_name, $chk_name);     // --> TRUE
 
$chk_name="-=mAnHuNtEr=-"; // Регистр и служебные символы
chk_similarity($admin_name, $chk_name);     // --> FALSE
chk_similarity($admin_name, $chk_name, 1);  // --> TRUE
 
$chk_name="ManHanter";     // Слово не похоже
chk_similarity($admin_name, $chk_name);     // --> FALSE
chk_similarity($admin_name, $chk_name, 1);  // --> FALSE

Теперь враг не пройдет :) Функцию без особого труда можно модифицировать, чтобы она возвращала регулярное выражение для поиска соответствий по базе.
Теги:
слово
Добавлено: 21 Сентября 2013 01:17:43 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...