Применение алгоритмов нечеткого поиска в PHP

Тема в разделе "PHP", создана пользователем ZiX, 6 ноя 2012.

Статус темы:
Закрыта.
Модераторы: latteo
  1. ZiX

    ZiX Коддинг, Парсинг

    Moderator
    Регистр.:
    9 июл 2011
    Сообщения:
    1.378
    Симпатии:
    562
    Нашел статейку на хабре хорошую http://habrahabr.ru/post/115394/. Язык php плохо знаю. Надеюсь на вашу помощь!
    Есть класс:
    PHP:
    class Corrector
    {
     
        public 
    $conn;
     
        public function 
    __construct()
        {
            
    $this->conn = new mysqli("host""login""password""db");
        }
       
        private function 
    translitIt($str)
        {
            
    $tr = array(
                    
    "А"=>"A","Б"=>"B","В"=>"V","Г"=>"G",
                    
    "Д"=>"D","Е"=>"E","Ж"=>"J","З"=>"Z","И"=>"I",
                    
    "Й"=>"Y","К"=>"K","Л"=>"L","М"=>"M","Н"=>"N",
                    
    "О"=>"O","П"=>"P","Р"=>"R","С"=>"S","Т"=>"T",
                    
    "У"=>"U","Ф"=>"F","Х"=>"H","Ц"=>"TS","Ч"=>"CH",
                    
    "Ш"=>"SH","Щ"=>"SCH","Ъ"=>"","Ы"=>"YI","Ь"=>"",
                    
    "Э"=>"E","Ю"=>"YU","Я"=>"YA","а"=>"a","б"=>"b",
                    
    "в"=>"v","г"=>"g","д"=>"d","е"=>"e","ж"=>"j",
                    
    "з"=>"z","и"=>"i","й"=>"y","к"=>"k","л"=>"l",
                    
    "м"=>"m","н"=>"n","о"=>"o","п"=>"p","р"=>"r",
                    
    "с"=>"s","т"=>"t","у"=>"u","ф"=>"f","х"=>"h",
                    
    "ц"=>"ts","ч"=>"ch","ш"=>"sh","щ"=>"sch","ъ"=>"y",
                    
    "ы"=>"yi","ь"=>"'","э"=>"e","ю"=>"yu","я"=>"ya"
                
    );
                return 
    strtr($str,$tr);
        }
     
        public function 
    correctWord($words)
        {
            
    $this->conn->query("SET NAMES utf8");
            
    $this->conn->query("SET CHARACTER SET utf8");
           
            
    $this->conn->query("SET charset utf8");
            
    $this->conn->query("SET character_set_client = utf8");
            
    $this->conn->query("SET character_set_connection = utf8");
            
    $this->conn->query("SET character_set_results = utf8");
            
    $this->conn->query("SET collation_connection = utf8_general_ci");   
     
            
    //Запрос для получения словаря
            
    $query "SELECT ru_words, translit FROM word_list";
     
            
    //Получение словаря
            
    $word_list = array();
     
            if(
    $stmt $this->conn->prepare($query))
            {
                    
    $stmt->execute();
                    
    $stmt->bind_result($ru_word$translit);
                    while(
    $stmt->fetch())
                    {
                        
    $word_translit[$ru_word] = $translit;
                    }
            }
     
            
    //Перебираем массив введенных слов и записываем результаты в новый массив
            
    $num 0;
            while(
    $num count($words))
            {
                
    $myWord $words[$num];
                
    $num++;
     
                if(isset(
    $word_list[$myWord]))
                {
                    
    $correct[] .= $myWord;
                }
                else
                {
                    
    $enteredWord $this->translitIt($myWord);
     
            
    $possibleWord NULL;
     
            foreach(
    $word_translit as $n=>$k)
            {
                if(
    levenshtein(metaphone($enteredWord), metaphone($k)) < (mb_strlen(metaphone($enteredWord))/2)+1)
                {
                    if(
    levenshtein($enteredWord$k) < mb_strlen($enteredWord)/2+1)
                    {
                        
    $possibleWord[$n] = $k;
                    }
                }
            }
     
            
    $similarity 0;
            
    $meta_similarity 0;
            
    $min_levenshtein 1000;
            
    $meta_min_levenshtein 1000;
     
                    
    //Считаем минимальное расстояние Левенштейна
                   
                    
    if(count($possibleWord))
                    {
                        foreach(
    $possibleWord as $n)
                        {
                            
    $min_levenshtein min($min_levenshteinlevenshtein($n$enteredWord));
                        }
     
                        
    //Считаем максимальное значение подобности слов
                        
    foreach($possibleWord as $n)
                        {
                            if(
    levenshtein($k$enteredWord) == $min_levenshtein)
                            {
                                
    $similarity max($similaritysimilar_text($n$enteredWord));
                            }
                        }
     
                        
    $result NULL;
                       
                        
    //Проверка всего слова
                        
    foreach($possibleWord as $n=>$k)
                        {
                            if(
    levenshtein($k$enteredWord) <= $min_levenshtein)
                            {
                                if(
    similar_text($k$enteredWord) >= $similarity)
                                {
                                    
    $result[$n] = $k;
                                }
                            }
                        }
     
                        foreach(
    $result as $n)
                        {
                            
    $meta_min_levenshtein min($meta_min_levenshteinlevenshtein(metaphone($n), metaphone($enteredWord)));
                        }
                       
                        
    //Считаем максимальное значение подобности слов
                        
    foreach($result as $n)
                        {
                            if(
    levenshtein($k$enteredWord) == $meta_min_levenshtein)
                            {
                                
    $meta_similarity max($meta_similaritysimilar_text(metaphone($n), metaphone($enteredWord)));
                            }
                        }
                       
                        
    $meta_result NULL;
                       
                        
    //Проверка через метафон
                        
    foreach($result as $n=>$k)
                        {
                            if(
    levenshtein(metaphone($k), metaphone($enteredWord)) <= $meta_min_levenshtein)
                            {
                                    if(
    similar_text(metaphone($k), metaphone($enteredWord)) >= $meta_similarity)
                                    {
                                        
    $meta_result[$n] = $k;
                                    }
                            }
                        }
                       
                       
                        
    $correct[] .= key($meta_result);
     
                    }
                    else
                    {
                        
    $correct[] .= $myWord;
                    }
                }
            }
            return 
    $correct;
        }
     
    }
    Как заставить это все работать? я не могу понять где вводная переменная. И где тут правильное слово возвращается?
    Помогите пожалуйста. Лучше на пальцах, то есть $echo
    В классах не разбираюсь.
    Кому интересно хорошая база тут:http://narod.ru/disk/7662133001/dictionary-rus.rar.html
     
  2. Viodele

    Viodele Механик

    Administrator
    Регистр.:
    17 дек 2011
    Сообщения:
    110
    Симпатии:
    479
    PHP:
    $words = array ('Привет''мир');

    $cor = new Corrector ( );
    $result $cor->correctWord($words);

    die (
    '<pre>' var_export ($resulttrue));
     
    ZiX нравится это.
  3. ZiX

    ZiX Коддинг, Парсинг

    Moderator
    Регистр.:
    9 июл 2011
    Сообщения:
    1.378
    Симпатии:
    562
    Спасибо Вам, но что-то не заводится.
    PHP:
    $words = array ('Язик');
    Результат:
    Код:
    array (
      0 => 'Язик',
    )
    Огорчает.
     
  4. Viodele

    Viodele Механик

    Administrator
    Регистр.:
    17 дек 2011
    Сообщения:
    110
    Симпатии:
    479
    Приведенный Вами код подразумевает то, что Вы умеете настраивать работу БД и верно прописали параметры подключения в строке
    PHP:
    $this->conn = new mysqli("host""login""password""db");
    Также, компилятор PHP должен иметь установленное расширение для работы с реляционными БД MySQLi.
     
    ZiX нравится это.
  5. ZiX

    ZiX Коддинг, Парсинг

    Moderator
    Регистр.:
    9 июл 2011
    Сообщения:
    1.378
    Симпатии:
    562
    Да базу настроил, к базе доступ есть. Скрипт очень долго работает. Соединение с базой настроенно правильно. В базе два столбца ru_word, translit в кодировке cp1251_general_ci. В коде кодировку тоже на cp1251 менял.
    Пример базы
    КРАТНЫЙ, KRATNIy


    Ура нашел проблему, в базе стояли невидимые символы в конце слов КРАТНЫЙ\r, KRATNIy\r
    Все работает!!!!
     
  6. Viodele

    Viodele Механик

    Administrator
    Регистр.:
    17 дек 2011
    Сообщения:
    110
    Симпатии:
    479
    Символ \r - это дескриптор возврата кареты (CR, код 10). Кстати, не совсем уверен на счет кодировки. Везде по скрипту, на сколько я вижу, идет установка кодировки utf8 для БД. Соответственно, файл скрипта тоже должен быть в utf8. Хотя, может я просто не до конца разобрался с кодом. Проверьте на всякий случай.
     
  7. ZiX

    ZiX Коддинг, Парсинг

    Moderator
    Регистр.:
    9 июл 2011
    Сообщения:
    1.378
    Симпатии:
    562
    Загрузил базу около 1300000 слов, пробую скрипт, а он мне пустую страничку выдает. С такой-же базой но 40 000 слов работает на ура. В чем может быть проблема. Уже в php.ini все поправил.
    max_execution_time = 200
    max_input_time = 200
    Все равно не работает с большой базой. Куда копать?
     
  8. Viodele

    Viodele Механик

    Administrator
    Регистр.:
    17 дек 2011
    Сообщения:
    110
    Симпатии:
    479
    Для начала, в сторону выделения памяти.
    PHP:
    ini_set("memory_limit""64M");
     
Статус темы:
Закрыта.