torrentpier-lts/library/includes/classes/correct.php

3120 lines
67 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
if (!defined('BB_ROOT')) die(basename(__FILE__));
/**
* Automatic correction of the language for words in the text because of the wrong keyboard layout
* Автоматическое исправление языка для слов в тексте из-за неправильной раскладки клавиатуры
*
* Purpose
* * Корректировка поисковых запросов
* * Корректировка существующих и новых текстов, публикуемых посетителями на веб-сайтах.
*
* Features
* * Режим SIMILAR_CHARS. Исправление ошибочно набранных букв в словах, которые выглядят
* одинаково в разных раскладках клавиатуры. Незаметные латинские буквы среди русских
* исправляются в русские и наоборот. Алгоритм работает достаточно надёжно и быстро.
* * Режим KEYBOARD_LAYOUT. Исправление ошибочно набранных слов в другой раскладке клавиатуры.
* Для определения языка используются N-граммы. Алгоритм может иногда ошибаться,
* работает в разы медленнее, чем SIMILAR_CHARS. Алгоритм постоянно совершенствуется.
* Для поддержания качества существует тестовый набор слов, который в поставку не входит.
* * Двухстороннее исправление слов для русского и английского языка.
* * Исправление слов на смешанном языке.
* * Кодировка символов — UTF-8.
* * Класс может работать без расширений mbstring и iconv!
*
* Examples
* "\xd1\x81\xd0\xbesm\xd0\xbe" => 'cosmo' (2 первых и последняя буква — ошибочные)
* "\x78\x70\x65н" => 'хрен' (первые 3 буквы — ошибочные)
* "вебvfcnth" => 'вебмастер'
* "webьфыеук" => 'webmaster'
* "цццюмуыеш.ru" => 'www.vesti.ru'
* "\x54.\x43.\x48\x61вка" => 'Т.С.Навка'
*
* Hints
* Типичный пример алгоритма работы для поля ввода с автодополнением:
* 1. Сделать выборку по исходному запросу;
* 2. Если есть результат, возвратить его и исходный запрос;
* 3. Иначе скорректировать исходный запрос через Text_LangCorrect;
* 4. Если исходный и скорректированный запрос совпадает, возвратить пустой результат и исходный запрос;
* 5. Иначе сделать выборку по скорректированному запросу;
* 6. Возвратить результат. Если результат не пустой, возвратить скорректированный запрос, иначе исходный.
*
* License
* Только для некоммерческого использования!
*
* @link http://code.google.com/p/php-lang-correct/
* @license http://creativecommons.org/licenses/by-nc-sa/3.0/
* @author Nasibullin Rinat
* @version 1.4.3
*
* Fork: https://github.com/b1rdex/text-lang-correct | Aug 4 2023 | 0.1.8
*/
class Text_LangCorrect
{
/**
* Флаг для исправления ошибочно набранных букв в словах,
* которые выглядят одинаково в разных раскладках клавиатуры.
* Алгоритм работает достаточно надёжно и быстро.
*/
const SIMILAR_CHARS = 1;
/**
* Флаг для исправления ошибочно набранных слов в другой раскладке клавиатуры.
* Алгоритм может иногда ошибаться, работает в разы медленнее, чем SIMILAR_CHARS.
*/
const KEYBOARD_LAYOUT = 2;
/**
* Флаг для добавления исправлений, если влючён флаг KEYBOARD_LAYOUT
* Синтаксис и пример: "(,.cn=>бюст)"
* ^ ^^ ^
*/
const ADD_FIX = 4;
#английский (all)
private $en = '[a-zA-Z]';
#английский (uppercase)
private $en_uc = '[A-Z]';
#английский + символы, которые м.б. набраны по ошибке в английской раскладке клавиатуры вместо русских букв (all)
private $en_sc = '[a-zA-Z\'`~<>,.:;{}\[\]"]';
#символы, которые м.б. набраны по ошибке в английской раскладке клавиатуры вместо русских букв
private $sc = '[\'`~<>,.:;{}\[\]"]';
private $no_sc = '[^\'`~<>,.:;{}\[\]"]';
#русский + татарский (all)
private $tt = '[\xd0-\xd3][\x80-\xbf]
(?<=\xd0[\x90-\xbf\x81]|\xd1[\x80-\x8f\x91]|\xd2[\x96\x97\xa2\xa3\xae\xaf\xba\xbb]|\xd3[\x98\x99\xa8\xa9])';
#русский + татарский (uppercase)
private $tt_uc = '[\xd0\xd2\xd3][\x81-\xba]
(?<=\xd0[\x90-\xaf\x81]|\xd2[\x96\xa2\xae\xba]|\xd3[\x98\xa8])';
#русский + татарский (для фильтрованных текстов) (all)
private $tt_f = '[\xd0-\xd3][\x80-\xbf]
#комментируем для увеличения скорости, т.к. остальные символы отфильтрованы
#(?<=\xd0[\x90-\xbf\x81]|\xd1[\x80-\x8f\x91]|\xd2[\x96\x97\xa2\xa3\xae\xaf\xba\xbb]|\xd3[\x98\x99\xa8\xa9])
';
#гласная (vowel) (lowercase)
private $vowel_lc = array(
'tt' => '\xd0[\xb0\xb5\xb8\xbe]|\xd1[\x83\x8b\x8d\x8e\x8f\x91] #аеиоуыэюяё (гласные, 10 шт.)
#| \xd0[\x90\x95\x98\x9e\xa3\xab\xad\xae\xaf\x81] #АЕИОУЫЭЮЯЁ (гласные, 10 шт.)
',
'en' => '[aeiouy]', #латинских 6 шт.
);
#согласная (consonant) + графические знаки для русского языка (ъ, ь) (lowercase)
private $consonant_lc = array(
'tt' => '\xd0[\xb1-\xb4\xb6\xb7\xb9\xba-\xbd\xbf]|\xd1[\x80\x81\x82\x84-\x89\x8a\x8c] #бвгджзйклмнпрстфхцчшщ ъь (согласные, 21+2 шт.)
#| \xd0[\x91-\x94\x96\x97\x99\x9a-\x9d\x9f-\xa2\xa4-\xa9\xaa\xac] #БВГДЖЗЙКЛМНПРСТФХЦЧШЩ ЪЬ (согласные, 21+2 шт.)
',
'en' => '[bcdfghjklmnpqrstvwxz]', #латинских 20 шт.
);
private $words_exceptions = array(
'tt' => array(
'трлн' => null,
'ющенко' => null,
'мебельград' => null,
'дэнис' => null,
),
'en' => array(
'heuer' => null,
),
);
#русские буквы, похожие на англ. (uppercase)
private $ru_similar_uc = "\xd0[\x90\x92\x95\x9a\x9c\x9d\x9e\xa0-\xa3\xa5]";
#русские буквы, похожие на англ. (all)
private $ru_similar = "\xd0[\x90\x92\x95\x9a\x9c\x9d\x9e\xa0-\xa3\xa5\xb0\xb5\xbe]|\xd1[\x80\x81\x83\x85]";
#англ. буквы, похожие на русские (uppercase)
private $en_similar_uc = '[ABEKMHOPCTYX]';
/*
#$tt_fake = '\xd0[\xb0\xb5\xbe\x90\x92\x95\x9a\x9c\x9d\x9e\xa0\xa1\xa2\xa3\xa5]|\xd1[\x80\x81\x83\x85]';
$tt_fake = '[\xd0\xd1][\x80-\xbe]
(?<=\xd0[\xb0\xb5\xbe\x90\x92\x95\x9a\x9c\x9d\x9e\xa0\xa1\xa2\xa3\xa5]|\xd1[\x80\x81\x83\x85])';
$en_fake = '[aeopcyxABEKMHOPCTYX]';
*/
#уникальные русские буквы
/*
CASE_UPPER, case_lower
"\xd0\x81", "\xd1\x91", #Ё ё
"\xd0\x91", "\xd0\xb1", #Б б
"\xd0\x92", "\xd0\xb2", #В в
"\xd0\x93", "\xd0\xb3", #Г г
"\xd0\x94", "\xd0\xb4", #Д д
"\xd0\x96", "\xd0\xb6", #Ж ж
"\xd0\x97", "\xd0\xb7", #З з
"\xd0\x98", "\xd0\xb8", #И и
"\xd0\x99", "\xd0\xb9", #Й й
"\xd0\xba", #К к
"\xd0\x9b", "\xd0\xbb", #Л л
"\xd0\xbd", #Н н
"\xd0\x9f", "\xd0\xbf", #П п
"\xd1\x82", #Т т
"\xd0\xa4", "\xd1\x84", #Ф ф
"\xd0\xa6", "\xd1\x86", #Ц ц
"\xd0\xa7", "\xd1\x87", #Ч ч
"\xd0\xa8", "\xd1\x88", #Ш ш
"\xd0\xa9", "\xd1\x89", #Щ щ
"\xd0\xaa", "\xd1\x8a", #Ъ ъ
"\xd0\xab", "\xd1\x8b", #Ы ы
"\xd0\xac", "\xd1\x8c", #Ь ь
"\xd0\xad", "\xd1\x8d", #Э э
"\xd0\xae", "\xd1\x8e", #Ю ю
"\xd0\xaf", "\xd1\x8f", #Я я
*/
#$tt_uniq = "\xd0[\xb1-\xb4\xb6-\xbb\xbd\xbf\x81\x91-\x94\x96-\x99\x9b\x9f\xa4\xa6-\xaf]|\xd1[\x82\x84\x86-\x8f\x91]";
private $tt_uniq = "[\xd0\xd1][\x82-\xbf]
(?<=\xd0[\xb1-\xb4\xb6-\xbb\xbd\xbf\x81\x91-\x94\x96-\x99\x9b\x9f\xa4\xa6-\xaf]|\xd1[\x82\x84\x86-\x8f\x91])";
#уникальные латинские буквы
/*
CASE_UPPER, case_lower
"\x42", "\x62", #B b
"\x44", "\x64", #D d
"\x46", "\x66", #F f
"\x68", #H h
"\x49", "\x69", #I i
"\x4a", "\x6a", #J j
"\x6b", #K k
"\x4c", "\x6c", #L l
"\x6d", #M m
"\x4e", "\x6e", #N n
"\x51", "\x71", #Q q
"\x52", "\x72", #R r
"\x53", "\x73", #S s
"\x74", #T t
"\x55", "\x75", #U u
"\x56", "\x76", #V v
"\x57", "\x77", #W w
"\x5a", "\x7a", #Z z
*/
private $en_uniq = "[\x42\x44\x46\x49\x4a\x4c\x4e\x51\x52\x53\x55\x57\x56\x5a\x62\x64\x66\x68\x69\x6a-\x6e\x71-\x77\x7a]";
private $table_flip; #array
private $words; #corrected words
private $en_correct; #string
private $tt_correct; #string
private $mode; #bool
private $is_flip = false;
private $method = 0;
private $table = array(
#метод 0: таблица исправления ошибочно набранных букв, которые выглядят одинаково (русский <--> английский)
0 => array(
#lowercase #UPPERCASE
"\xd0\xb0" => 'a', "\xd0\x90" => 'A',
"\xd0\x92" => 'B',
"\xd0\xb5" => 'e', "\xd0\x95" => 'E',
"\xd0\x9a" => 'K',
"\xd0\x9c" => 'M',
"\xd0\x9d" => 'H',
"\xd0\xbe" => 'o', "\xd0\x9e" => 'O',
"\xd1\x80" => 'p', "\xd0\xa0" => 'P',
"\xd1\x81" => 'c', "\xd0\xa1" => 'C',
"\xd0\xa2" => 'T',
"\xd1\x83" => 'y', "\xd0\xa3" => 'Y',
"\xd1\x85" => 'x', "\xd0\xa5" => 'X',
),
#метод 1: таблица исправления ошибочно набранных букв в другой раскладке клавиатуры (русский <--> английский)
1 => array(
#CASE_UPPER #case_lower
"\xd0\x81" => '~', "\xd1\x91" => '`', #Ё ё
"\xd0\x90" => 'F', "\xd0\xb0" => 'f', #А а
"\xd0\x91" => '<', "\xd0\xb1" => ',', б
"\xd0\x92" => 'D', "\xd0\xb2" => 'd', #В в
"\xd0\x93" => 'U', "\xd0\xb3" => 'u', г
"\xd0\x94" => 'L', "\xd0\xb4" => 'l', #Д д
"\xd0\x95" => 'T', "\xd0\xb5" => 't', #Е е
"\xd0\x96" => ':', "\xd0\xb6" => ';', #Ж ж
"\xd0\x97" => 'P', "\xd0\xb7" => 'p', #З з
"\xd0\x98" => 'B', "\xd0\xb8" => 'b', #И и
"\xd0\x99" => 'Q', "\xd0\xb9" => 'q', #Й й
"\xd0\x9a" => 'R', "\xd0\xba" => 'r', #К к
"\xd0\x9b" => 'K', "\xd0\xbb" => 'k', #Л л
"\xd0\x9c" => 'V', "\xd0\xbc" => 'v', #М м
"\xd0\x9d" => 'Y', "\xd0\xbd" => 'y', #Н н
"\xd0\x9e" => 'J', "\xd0\xbe" => 'j', #О о
"\xd0\x9f" => 'G', "\xd0\xbf" => 'g', #П п
#CASE_UPPER #case_lower
"\xd0\xa0" => 'H', "\xd1\x80" => 'h', #Р р
"\xd0\xa1" => 'C', "\xd1\x81" => 'c', #С с
"\xd0\xa2" => 'N', "\xd1\x82" => 'n', #Т т
"\xd0\xa3" => 'E', "\xd1\x83" => 'e', #У у
"\xd0\xa4" => 'A', "\xd1\x84" => 'a', #Ф ф
"\xd0\xa5" => '{', "\xd1\x85" => '[', #Х х
"\xd0\xa6" => 'W', "\xd1\x86" => 'w', #Ц ц
"\xd0\xa7" => 'X', "\xd1\x87" => 'x', #Ч ч
"\xd0\xa8" => 'I', "\xd1\x88" => 'i', #Ш ш
"\xd0\xa9" => 'O', "\xd1\x89" => 'o', #Щ щ
"\xd0\xaa" => '}', "\xd1\x8a" => ']', #Ъ ъ
"\xd0\xab" => 'S', "\xd1\x8b" => 's', #Ы ы
"\xd0\xac" => 'M', "\xd1\x8c" => 'm', #Ь ь
"\xd0\xad" => '"', "\xd1\x8d" => "'", #Э э
"\xd0\xae" => '>', "\xd1\x8e" => '.', #Ю ю
"\xd0\xaf" => 'Z', "\xd1\x8f" => 'z', #Я я
),
);
#несуществующие N-граммы для гласных букв
private $vowels3_lc = array(
'en' => array(
'aea' => 0,
'aei' => 1,
'aeo' => 2,
'aeu' => 3,
'aia' => 4,
'aie' => 5,
'aii' => 6,
'aoi' => 7,
'aou' => 8,
'aue' => 9,
'aya' => 10,
'aye' => 11,
'ayi' => 12,
'ayo' => 13,
'ayu' => 14,
'eae' => 15,
'eau' => 16,
'eea' => 17,
'eei' => 18,
'eeu' => 19,
'eia' => 20,
'eiu' => 21,
'eoi' => 22,
'eou' => 23,
'eya' => 24,
'eye' => 25,
'eyi' => 26,
'eyo' => 27,
'iae' => 28,
'iai' => 29,
'iao' => 30,
'iau' => 31,
'iei' => 32,
'ieu' => 33,
'ioa' => 34,
'ioe' => 35,
'iou' => 36,
'iya' => 37,
'oae' => 38,
'oea' => 39,
'oei' => 40,
'oeo' => 41,
'oeu' => 42,
'oey' => 43,
'oia' => 44,
'oie' => 45,
'ooe' => 46,
'ooi' => 47,
'oou' => 48,
'oua' => 49,
'oue' => 50,
'oui' => 51,
'oya' => 52,
'oye' => 53,
'oyi' => 54,
'oyo' => 55,
'uae' => 56,
'uai' => 57,
'uay' => 58,
'uea' => 59,
'uee' => 60,
'uei' => 61,
'ueo' => 62,
'ueu' => 63,
'uey' => 64,
'uia' => 65,
'uie' => 66,
'uio' => 67,
'uiu' => 68,
'uoa' => 69,
'uoi' => 70,
'uou' => 71,
'uoy' => 72,
'uya' => 73,
'uye' => 74,
'uyi' => 75,
'yae' => 76,
'yao' => 77,
'yau' => 78,
'yea' => 79,
'yei' => 80,
'yeo' => 81,
'yey' => 82,
'yie' => 83,
'yoi' => 84,
'you' => 85,
'yoy' => 86,
'yua' => 87,
),
'tt' => array(
'аау' => 0,
'аео' => 1,
'аеу' => 2,
'аиа' => 3,
'аио' => 4,
'аиу' => 5,
'аои' => 6,
'ауэ' => 7,
'аяя' => 8,
'еаэ' => 9,
'еее' => 10,
'еео' => 11,
'еоа' => 12,
'еои' => 13,
'еоо' => 14,
'еую' => 15,
'еуя' => 16,
'еуё' => 17,
'иау' => 18,
'иео' => 19,
'иие' => 20,
'иоа' => 21,
'иои' => 22,
'иоу' => 23,
'иоэ' => 24,
'ияе' => 25,
'ияи' => 26,
'ияю' => 27,
'оаэ' => 28,
'оео' => 29,
'оею' => 30,
'оие' => 31,
'оуе' => 32,
'оуя' => 33,
'оюе' => 34,
'оюю' => 35,
'ояе' => 36,
'уео' => 37,
'уюю' => 38,
),
);
#несуществующие N-граммы для согласных букв
private $consonants4_lc = array(
'en' => array(
'bldg' => 0,
'blvd' => 1,
'bscr' => 2,
'bstr' => 3,
'cbcm' => 4,
'cbft' => 5,
'chfr' => 6,
'chmn' => 7,
'chsc' => 8,
'chsh' => 9,
'chst' => 10,
'chth' => 11,
'chts' => 12,
'ckbr' => 13,
'ckch' => 14,
'ckcl' => 15,
'ckdr' => 16,
'ckgr' => 17,
'cksc' => 18,
'cksf' => 19,
'cksh' => 20,
'cksk' => 21,
'cksl' => 22,
'cksm' => 23,
'cksn' => 24,
'cksp' => 25,
'ckst' => 26,
'cksw' => 27,
'ckth' => 28,
'cktr' => 29,
'ckwh' => 30,
'cmps' => 31,
'dspr' => 32,
'dstr' => 33,
'dthw' => 34,
'ffsc' => 35,
'ffsh' => 36,
'ffsp' => 37,
'fthl' => 38,
'ftsm' => 39,
'ftsp' => 40,
'gdns' => 41,
'ghbr' => 42,
'ghfl' => 43,
'ghsh' => 44,
'ghtb' => 45,
'ghtc' => 46,
'ghtf' => 47,
'ghth' => 48,
'ghtj' => 49,
'ghtl' => 50,
'ghtm' => 51,
'ghtn' => 52,
'ghtr' => 53,
'ghts' => 54,
'ghtw' => 55,
'hdbk' => 56,
'hnst' => 57,
'jctn' => 58,
'khsh' => 59,
'khst' => 60,
'lchr' => 61,
'ldpr' => 62,
'ldsh' => 63,
'ldsm' => 64,
'ldsp' => 65,
'ldst' => 66,
'lfsk' => 67,
'lfth' => 68,
'lgth' => 69,
'llfl' => 70,
'llfr' => 71,
'llph' => 72,
'llpl' => 73,
'llsh' => 74,
'llsp' => 75,
'llst' => 76,
'lltr' => 77,
'llwr' => 78,
'lmcr' => 79,
'lmsm' => 80,
'lnrk' => 81,
'lnsh' => 82,
'lptr' => 83,
'lsgr' => 84,
'lshm' => 85,
'lshw' => 86,
'lstr' => 87,
'lthf' => 88,
'ltsf' => 89,
'ltsh' => 90,
'ltst' => 91,
'mbsc' => 92,
'mbsh' => 93,
'mbsk' => 94,
'mbst' => 95,
'mddx' => 96,
'mdnt' => 97,
'mpbl' => 98,
'mpgr' => 99,
'mphl' => 100,
'mphr' => 101,
'mpsh' => 102,
'mpst' => 103,
'mptl' => 104,
'mptn' => 105,
'mptr' => 106,
'mpts' => 107,
'mscr' => 108,
'mstr' => 109,
'nchb' => 110,
'nchl' => 111,
'nchm' => 112,
'nchn' => 113,
'nchp' => 114,
'nchr' => 115,
'nchw' => 116,
'nctl' => 117,
'nctn' => 118,
'ndbk' => 119,
'ndbr' => 120,
'ndch' => 121,
'ndfl' => 122,
'ndgl' => 123,
'ndgr' => 124,
'ndsc' => 125,
'ndsh' => 126,
'ndsl' => 127,
'ndsm' => 128,
'ndsp' => 129,
'ndst' => 130,
'ndsw' => 131,
'ndth' => 132,
'ndwr' => 133,
'ngcr' => 134,
'ngsg' => 135,
'ngsh' => 136,
'ngsm' => 137,
'ngsp' => 138,
'ngst' => 139,
'ngth' => 140,
'ngtz' => 141,
'nksg' => 142,
'nksh' => 143,
'nksm' => 144,
'nkst' => 145,
'nsch' => 146,
'nscr' => 147,
'nsgr' => 148,
'nshr' => 149,
'nskr' => 150,
'nspl' => 151,
'nspr' => 152,
'nssh' => 153,
'nstr' => 154,
'ntbr' => 155,
'nthl' => 156,
'nthr' => 157,
'nths' => 158,
'ntsh' => 159,
'ntsm' => 160,
'phth' => 161,
'pstr' => 162,
'pthr' => 163,
'pths' => 164,
'ptwr' => 165,
'rbst' => 166,
'rchb' => 167,
'rchd' => 168,
'rchl' => 169,
'rchm' => 170,
'rchn' => 171,
'rchp' => 172,
'rchw' => 173,
'rdsh' => 174,
'rdsm' => 175,
'rdst' => 176,
'rghs' => 177,
'rkpl' => 178,
'rksc' => 179,
'rksh' => 180,
'rksk' => 181,
'rksm' => 182,
'rksp' => 183,
'rkst' => 184,
'rldl' => 185,
'rldw' => 186,
'rlfr' => 187,
'rmch' => 188,
'rmst' => 189,
'rmth' => 190,
'rnbl' => 191,
'rndl' => 192,
'rnsk' => 193,
'rnsp' => 194,
'rnst' => 195,
'rsch' => 196,
'rscr' => 197,
'rshl' => 198,
'rshn' => 199,
'rspr' => 200,
'rstl' => 201,
'rstr' => 202,
'rsts' => 203,
'rstw' => 204,
'rtbr' => 205,
'rtch' => 206,
'rtcr' => 207,
'rthb' => 208,
'rthc' => 209,
'rthd' => 210,
'rthf' => 211,
'rthl' => 212,
'rthm' => 213,
'rthq' => 214,
'rthr' => 215,
'rths' => 216,
'rthw' => 217,
'rtsh' => 218,
'rtsm' => 219,
'rtsp' => 220,
'rtsw' => 221,
'schl' => 222,
'schm' => 223,
'schn' => 224,
'schw' => 225,
'scrp' => 226,
'sgmt' => 227,
'shcl' => 228,
'shkh' => 229,
'shpr' => 230,
'shpt' => 231,
'shst' => 232,
'shtr' => 233,
'shwh' => 234,
'smth' => 235,
'ssrs' => 236,
'ssst' => 237,
'sstd' => 238,
'sstr' => 239,
'stcr' => 240,
'sthm' => 241,
'stpl' => 242,
'stpr' => 243,
'stsc' => 244,
'stwr' => 245,
'tblt' => 246,
'tchb' => 247,
'tchc' => 248,
'tchd' => 249,
'tchf' => 250,
'tchl' => 251,
'tchm' => 252,
'tchp' => 253,
'tchw' => 254,
'thdr' => 255,
'thsh' => 256,
'thsk' => 257,
'thsp' => 258,
'thst' => 259,
'tsch' => 260,
'tspr' => 261,
'tstr' => 262,
'tthr' => 263,
'ttsb' => 264,
'tzkr' => 265,
'whsl' => 266,
'wnbr' => 267,
'wnpl' => 268,
'wnsf' => 269,
'wnsh' => 270,
'wnsm' => 271,
'wnsp' => 272,
'wnst' => 273,
'wnsw' => 274,
'wnth' => 275,
'wntr' => 276,
'wrnt' => 277,
'wsfl' => 278,
'wspr' => 279,
'wstr' => 280,
'xthl' => 281,
),
'tt' => array(
'блзд' => 0,
'бльд' => 1,
'брьс' => 2,
'бств' => 3,
'бстр' => 4,
'взбл' => 5,
'взбр' => 6,
'взгл' => 7,
'взгр' => 8,
'вздв' => 9,
'вздр' => 10,
'врвг' => 11,
'врск' => 12,
'вскл' => 13,
'вскр' => 14,
'вспл' => 15,
'вспр' => 16,
'вств' => 17,
'встр' => 18,
'всхл' => 19,
'всхр' => 20,
'втск' => 21,
'вхск' => 22,
'грск' => 23,
'гств' => 24,
'гтст' => 25,
'гшпр' => 26,
'двзд' => 27,
'джск' => 28,
'дрст' => 29,
'дскр' => 30,
'дств' => 31,
'дстр' => 32,
'дтск' => 33,
'жств' => 34,
'звзд' => 35,
'знст' => 36,
'зтьс' => 37,
'йздр' => 38,
'йкбр' => 39,
'йльн' => 40,
'йншт' => 41,
'йпфр' => 42,
'йств' => 43,
'йстр' => 44,
'йтск' => 45,
'йфст' => 46,
'йхсв' => 47,
'йхск' => 48,
'йхср' => 49,
'йхст' => 50,
'кскл' => 51,
'кскр' => 52,
'кспл' => 53,
'кспр' => 54,
'кств' => 55,
'кстн' => 56,
'кстр' => 57,
'лвст' => 58,
'лжск' => 59,
'лльн' => 60,
'лльс' => 61,
'лстр' => 62,
'лсть' => 63,
'льгв' => 64,
'льдж' => 65,
'льдк' => 66,
'льдм' => 67,
'льдс' => 68,
'льдф' => 69,
'льдц' => 70,
'льдш' => 71,
'льдъ' => 72,
'льдь' => 73,
'льзк' => 74,
'льзн' => 75,
'льзь' => 76,
'лькл' => 77,
'лькн' => 78,
'льпн' => 79,
'льпт' => 80,
'льск' => 81,
'льсн' => 82,
'льст' => 83,
'льтк' => 84,
'льтм' => 85,
'льтн' => 86,
'льтп' => 87,
'льтр' => 88,
'льтс' => 89,
'льтт' => 90,
'льтф' => 91,
'льфр' => 92,
'льцг' => 93,
'льчс' => 94,
'льшб' => 95,
'льшк' => 96,
'льшн' => 97,
'льшп' => 98,
'льшф' => 99,
'льшь' => 100,
'мбль' => 101,
'мбрс' => 102,
'мвзв' => 103,
'мздр' => 104,
'мств' => 105,
'мтск' => 106,
'нгль' => 107,
'нгст' => 108,
'ндгр' => 109,
'ндск' => 110,
'ндсп' => 111,
'ндшп' => 112,
'ндшт' => 113,
'нкск' => 114,
'нктн' => 115,
'нктс' => 116,
'нсгр' => 117,
'нскм' => 118,
'нскр' => 119,
'нспл' => 120,
'нств' => 121,
'нстк' => 122,
'нстр' => 123,
'нтгл' => 124,
'нтль' => 125,
'нтрб' => 126,
'нтрв' => 127,
'нтрг' => 128,
'нтрд' => 129,
'нтрм' => 130,
'нтрн' => 131,
'нтрп' => 132,
'нтрр' => 133,
'нтрф' => 134,
'нтск' => 135,
'нтст' => 136,
'нфск' => 137,
'нцкл' => 138,
'нцпл' => 139,
'нькн' => 140,
'ньск' => 141,
'ньчж' => 142,
'псск' => 143,
'пств' => 144,
'птск' => 145,
'рбск' => 146,
'ргпр' => 147,
'ргск' => 148,
'ргфл' => 149,
'рдск' => 150,
'рдсм' => 151,
'рдст' => 152,
'рздр' => 153,
'рзть' => 154,
'ркгр' => 155,
'ркск' => 156,
'рктн' => 157,
'рльс' => 158,
'рмск' => 159,
'рмтр' => 160,
'рнск' => 161,
'рпск' => 162,
'рсдр' => 163,
'рсск' => 164,
'рств' => 165,
'рстк' => 166,
'рстн' => 167,
'рстр' => 168,
'рстс' => 169,
'рсть' => 170,
'ртвл' => 171,
'ртвр' => 172,
'ртгр' => 173,
'рткр' => 174,
'ртпл' => 175,
'ртпр' => 176,
'ртск' => 177,
'ртсм' => 178,
'ртшк' => 179,
'ртьф' => 180,
'рхзв' => 181,
'рхпл' => 182,
'рхпр' => 183,
'рхсв' => 184,
'рхск' => 185,
'рхсм' => 186,
'рхср' => 187,
'рхтв' => 188,
'рхшт' => 189,
'рщвл' => 190,
'рьмл' => 191,
'скск' => 192,
'спрь' => 193,
'сспр' => 194,
'ссср' => 195,
'сств' => 196,
'сстр' => 197,
'ссшп' => 198,
'ствл' => 199,
'стрс' => 200,
'стрш' => 201,
'стск' => 202,
'стьб' => 203,
'стьд' => 204,
'стьс' => 205,
'ськн' => 206,
'сьмн' => 207,
'тмст' => 208,
'тпрр' => 209,
'трст' => 210,
'тскр' => 211,
'тств' => 212,
'тстр' => 213,
'ттль' => 214,
'ттск' => 215,
'тхск' => 216,
'фств' => 217,
'фстр' => 218,
'хств' => 219,
'хстр' => 220,
'хткл' => 221,
'хтск' => 222,
'хтсм' => 223,
'цстр' => 224,
),
);
#несуществующие биграммы в начале и конце слов
private $bigrams = array(
#ru
' ёё' => 0,
' ёа' => 0,
' ёб' => 0,
' ёв' => 0,
' ёг' => 0,
' ёд' => 0,
' ёе' => 0,
' ёз' => 0,
' ёи' => 0,
' ёй' => 0,
' ён' => 0,
' ёо' => 0,
' ёп' => 0,
' ёс' => 0,
' ёт' => 0,
' ёу' => 0,
' ёф' => 0,
' ёц' => 0,
' ёч' => 0,
' ёщ' => 0,
' ёъ' => 0,
' ёы' => 0,
' ёь' => 0,
' ёэ' => 0,
' ёю' => 0,
' ёя' => 0,
' аё' => 0,
' аа' => 0,
' ае' => 0,
' ач' => 0,
' аъ' => 0,
' аы' => 0,
' аь' => 0,
' аю' => 0,
' ая' => 0,
' бб' => 0,
' бв' => 0,
' бг' => 0,
' бж' => 0,
' бй' => 0,
' бк' => 0,
' бм' => 0,
' бн' => 0,
' бп' => 0,
' бс' => 0,
' бт' => 0,
' бф' => 0,
' бх' => 0,
' бц' => 0,
' бч' => 0,
' бш' => 0,
' бщ' => 0,
' бъ' => 0,
' вй' => 0,
' вф' => 0,
' вщ' => 0,
' вэ' => 0,
' вю' => 0,
' гё' => 0,
' гб' => 0,
' гз' => 0,
' гй' => 0,
' гк' => 0,
' гп' => 0,
' гс' => 0,
' гт' => 0,
' гф' => 0,
' гх' => 0,
' гц' => 0,
' гч' => 0,
' гш' => 0,
' гщ' => 0,
' гъ' => 0,
' гь' => 0,
' гэ' => 0,
' дб' => 0,
' дг' => 0,
' дд' => 0,
' дй' => 0,
' дк' => 0,
' дп' => 0,
' дс' => 0,
' дт' => 0,
' дф' => 0,
' дх' => 0,
' дц' => 0,
' дч' => 0,
' дш' => 0,
' дъ' => 0,
' дэ' => 0,
' еа' => 0,
' еб' => 0,
' еи' => 0,
' ео' => 0,
' ет' => 0,
' еу' => 0,
' ец' => 0,
#' еш' => 0,
' еъ' => 0,
' еы' => 0,
' еь' => 0,
' еэ' => 0,
' ея' => 0,
' жз' => 0,
' жй' => 0,
' жк' => 0,
' жл' => 0,
' жп' => 0,
' жс' => 0,
' жт' => 0,
' жф' => 0,
' жх' => 0,
' жц' => 0,
' жч' => 0,
' жш' => 0,
' жщ' => 0,
' жъ' => 0,
' жы' => 0,
' жь' => 0,
' жэ' => 0,
#' жю' => 0,
' жя' => 0,
' зб' => 0,
' зж' => 0,
' зз' => 0,
' зй' => 0,
' зк' => 0,
' зп' => 0,
' зс' => 0,
' зт' => 0,
' зф' => 0,
' зх' => 0,
' зц' => 0,
' зч' => 0,
' зш' => 0,
' зщ' => 0,
' зъ' => 0,
' зь' => 0,
' зэ' => 0,
' иё' => 0,
' иа' => 0,
' иф' => 0,
' иц' => 0,
' иъ' => 0,
' иы' => 0,
' иь' => 0,
' иэ' => 0,
' ия' => 0,
' йё' => 0,
' йа' => 0,
' йб' => 0,
' йв' => 0,
' йг' => 0,
' йд' => 0,
' йж' => 0,
' йз' => 0,
' йи' => 0,
' йй' => 0,
' йк' => 0,
' йл' => 0,
' йм' => 0,
' йн' => 0,
' йп' => 0,
' йр' => 0,
' йс' => 0,
' йт' => 0,
' йу' => 0,
' йф' => 0,
' йх' => 0,
' йц' => 0,
' йч' => 0,
' йш' => 0,
' йщ' => 0,
' йъ' => 0,
' йы' => 0,
' йь' => 0,
' йэ' => 0,
' йю' => 0,
' йя' => 0,
' кё' => 0,
' кб' => 0,
' кд' => 0,
' кж' => 0,
' кй' => 0,
' кк' => 0,
' кф' => 0,
' кц' => 0,
' кч' => 0,
' кщ' => 0,
' къ' => 0,
' кя' => 0,
' лв' => 0,
' лд' => 0,
' лз' => 0,
' лй' => 0,
' лк' => 0,
' лл' => 0,
' лм' => 0,
' лн' => 0,
' лп' => 0,
' лр' => 0,
' лс' => 0,
' лт' => 0,
' лф' => 0,
' лх' => 0,
' лц' => 0,
' лч' => 0,
' лш' => 0,
' лщ' => 0,
' лъ' => 0,
' лэ' => 0,
' мб' => 0,
' мв' => 0,
' мд' => 0,
' мж' => 0,
' мй' => 0,
' мк' => 0,
' мп' => 0,
' мт' => 0,
' мф' => 0,
' мц' => 0,
' мъ' => 0,
' мь' => 0,
' нб' => 0,
' нв' => 0,
' нг' => 0,
' нд' => 0,
' нж' => 0,
' нз' => 0,
' нй' => 0,
' нк' => 0,
' нл' => 0,
' нм' => 0,
' нн' => 0,
' нп' => 0,
' нс' => 0,
' нт' => 0,
' нф' => 0,
' нх' => 0,
' нц' => 0,
' нч' => 0,
' нш' => 0,
' нщ' => 0,
' нъ' => 0,
' оё' => 0,
' ои' => 0,
' оу' => 0,
' оъ' => 0,
' оы' => 0,
' оь' => 0,
' оэ' => 0,
' оя' => 0,
' пб' => 0,
' пв' => 0,
' пг' => 0,
' пд' => 0,
' пж' => 0,
' пз' => 0,
' пй' => 0,
' пк' => 0,
' пм' => 0,
' пп' => 0,
' пц' => 0,
' пщ' => 0,
' пъ' => 0,
' рб' => 0,
' рг' => 0,
' рз' => 0,
' рй' => 0,
' рк' => 0,
' рл' => 0,
' рм' => 0,
' рн' => 0,
' рп' => 0,
' рр' => 0,
' рф' => 0,
' рх' => 0,
' рч' => 0,
' рш' => 0,
' рщ' => 0,
' ръ' => 0,
' сй' => 0,
' сщ' => 0,
' тб' => 0,
' тг' => 0,
' тд' => 0,
' тж' => 0,
' тз' => 0,
' тй' => 0,
' тн' => 0,
' тт' => 0,
' тх' => 0,
' тц' => 0,
' тч' => 0,
' тш' => 0,
' тъ' => 0,
' уу' => 0,
' уъ' => 0,
' уы' => 0,
' уь' => 0,
' фб' => 0,
' фв' => 0,
' фг' => 0,
' фд' => 0,
' фж' => 0,
' фз' => 0,
' фй' => 0,
' фк' => 0,
' фм' => 0,
' фн' => 0,
' фп' => 0,
' фс' => 0,
' фх' => 0,
' фц' => 0,
' фч' => 0,
' фш' => 0,
' фщ' => 0,
' фъ' => 0,
' фэ' => 0,
' фя' => 0,
' хё' => 0,
' хб' => 0,
' хг' => 0,
' хд' => 0,
' хж' => 0,
' хз' => 0,
' хй' => 0,
' хк' => 0,
' хп' => 0,
' хс' => 0,
' хт' => 0,
' хф' => 0,
' хц' => 0,
' хч' => 0,
' хш' => 0,
' хщ' => 0,
' хъ' => 0,
' хы' => 0,
' хь' => 0,
#' хэ' => 0,
' хю' => 0,
' хя' => 0,
' цё' => 0,
' цб' => 0,
' цг' => 0,
' цд' => 0,
' цж' => 0,
' цй' => 0,
' цл' => 0,
' цм' => 0,
' цн' => 0,
' цп' => 0,
' цр' => 0,
' цс' => 0,
' цт' => 0,
' цф' => 0,
' цх' => 0,
' цц' => 0,
' цч' => 0,
' цш' => 0,
' цщ' => 0,
' цъ' => 0,
' ць' => 0,
' цэ' => 0,
' цю' => 0,
' ця' => 0,
' чб' => 0,
' чг' => 0,
' чд' => 0,
' чж' => 0,
' чз' => 0,
' чй' => 0,
' чн' => 0,
' чп' => 0,
' чс' => 0,
' чф' => 0,
' чц' => 0,
' чч' => 0,
' чщ' => 0,
' чъ' => 0,
' чы' => 0,
' чэ' => 0,
' чю' => 0,
' чя' => 0,
' шб' => 0,
' шг' => 0,
' шд' => 0,
' шж' => 0,
' шз' => 0,
' шй' => 0,
' шс' => 0,
' шф' => 0,
' шц' => 0,
' шч' => 0,
' шщ' => 0,
' шъ' => 0,
' шы' => 0,
' шэ' => 0,
' шю' => 0,
' шя' => 0,
' щб' => 0,
' щв' => 0,
' щг' => 0,
' щд' => 0,
' щж' => 0,
' щз' => 0,
' щй' => 0,
' щк' => 0,
' щл' => 0,
' щм' => 0,
' щн' => 0,
' що' => 0,
' щп' => 0,
' щр' => 0,
' щс' => 0,
' щт' => 0,
' щф' => 0,
' щх' => 0,
' щц' => 0,
' щч' => 0,
' щш' => 0,
' щщ' => 0,
' щъ' => 0,
' щы' => 0,
' щь' => 0,
' щэ' => 0,
' щю' => 0,
' щя' => 0,
' ъё' => 0,
' ъа' => 0,
' ъб' => 0,
' ъв' => 0,
' ъг' => 0,
' ъд' => 0,
' ъе' => 0,
' ъж' => 0,
' ъз' => 0,
' ъи' => 0,
' ъй' => 0,
' ък' => 0,
' ъл' => 0,
' ъм' => 0,
' ън' => 0,
' ъо' => 0,
' ъп' => 0,
' ър' => 0,
' ъс' => 0,
' ът' => 0,
' ъу' => 0,
' ъф' => 0,
' ъх' => 0,
' ъц' => 0,
' ъч' => 0,
' ъш' => 0,
' ъщ' => 0,
' ъъ' => 0,
' ъы' => 0,
' ъь' => 0,
' ъэ' => 0,
' ъю' => 0,
' ъя' => 0,
' ыё' => 0,
' ыа' => 0,
' ыб' => 0,
' ыв' => 0,
' ыг' => 0,
' ыд' => 0,
' ые' => 0,
' ыж' => 0,
' ыз' => 0,
' ыи' => 0,
' ый' => 0,
' ык' => 0,
' ыл' => 0,
' ын' => 0,
' ыо' => 0,
' ып' => 0,
' ыр' => 0,
' ыс' => 0,
' ыт' => 0,
' ыу' => 0,
' ыф' => 0,
' ых' => 0,
' ыц' => 0,
' ыч' => 0,
' ыш' => 0,
' ыщ' => 0,
' ыъ' => 0,
' ыы' => 0,
' ыь' => 0,
' ыэ' => 0,
' ыю' => 0,
' ыя' => 0,
' ьё' => 0,
' ьа' => 0,
' ьб' => 0,
' ьв' => 0,
' ьг' => 0,
' ьд' => 0,
' ье' => 0,
' ьж' => 0,
' ьз' => 0,
' ьи' => 0,
' ьй' => 0,
' ьк' => 0,
' ьл' => 0,
' ьм' => 0,
' ьн' => 0,
' ьо' => 0,
' ьп' => 0,
' ьр' => 0,
' ьс' => 0,
' ьт' => 0,
' ьу' => 0,
' ьф' => 0,
' ьх' => 0,
' ьц' => 0,
' ьч' => 0,
' ьш' => 0,
' ьщ' => 0,
' ьъ' => 0,
' ьы' => 0,
' ьь' => 0,
' ьэ' => 0,
' ью' => 0,
' ья' => 0,
' эё' => 0,
' эа' => 0,
' эе' => 0,
' эи' => 0,
' эц' => 0,
' эч' => 0,
' эщ' => 0,
' эъ' => 0,
' эы' => 0,
' эь' => 0,
' ээ' => 0,
' эю' => 0,
' юё' => 0,
' юе' => 0,
' юи' => 0,
' юй' => 0,
' юо' => 0,
' юу' => 0,
' юц' => 0,
' юш' => 0,
' ющ' => 0,
' юъ' => 0,
' юы' => 0,
' юь' => 0,
' юэ' => 0,
' юя' => 0,
' яё' => 0,
' яа' => 0,
' яе' => 0,
' яж' => 0,
' яо' => 0,
' яу' => 0,
' яф' => 0,
' яц' => 0,
' яъ' => 0,
' яы' => 0,
' яь' => 0,
' яэ' => 0,
' яю' => 0,
' яя' => 0,
'ёё' => 0,
'ёё ' => 0,
'ёа' => 0,
'ёа ' => 0,
'ёг ' => 0,
'ёе' => 0,
'ёе ' => 0,
'ёи' => 0,
'ёи ' => 0,
'ёй' => 0,
'ёо' => 0,
'ёо ' => 0,
'ёу' => 0,
'ёу ' => 0,
'ёф' => 0,
'ёф ' => 0,
'ёц ' => 0,
'ёч ' => 0,
'ёщ ' => 0,
'ёъ' => 0,
'ёъ ' => 0,
'ёы' => 0,
'ёы ' => 0,
'ёь' => 0,
'ёь ' => 0,
'ёэ' => 0,
'ёэ ' => 0,
'ёю' => 0,
'ёя' => 0,
'ёя ' => 0,
'аё ' => 0,
'аа ' => 0,
'аъ' => 0,
'аъ ' => 0,
'аы' => 0,
'аы ' => 0,
'аь' => 0,
'аь ' => 0,
'аэ ' => 0,
'бё ' => 0,
'бб ' => 0,
'бв ' => 0,
'бг ' => 0,
'бд ' => 0,
'бж ' => 0,
'бз ' => 0,
'бй' => 0,
'бй ' => 0,
'бк ' => 0,
'бм ' => 0,
'бн ' => 0,
'бп ' => 0,
'бт ' => 0,
'бф ' => 0,
'бх ' => 0,
'бц ' => 0,
'бч ' => 0,
'бш ' => 0,
'бщ ' => 0,
'бъ ' => 0,
'бэ ' => 0,
'вё ' => 0,
'вб ' => 0,
'вв ' => 0,
'вд ' => 0,
'вж' => 0,
'вж ' => 0,
'вз ' => 0,
'вй' => 0,
'вй ' => 0,
'вл ' => 0,
'вп ' => 0,
'вф ' => 0,
'вц ' => 0,
'вч ' => 0,
'вщ ' => 0,
'въ' => 0,
'въ ' => 0,
'вэ ' => 0,
'гё' => 0,
'гё ' => 0,
'гб ' => 0,
'гг ' => 0,
'гж' => 0,
'гж ' => 0,
'гз ' => 0,
'гй' => 0,
'гй ' => 0,
'гк ' => 0,
'гн ' => 0,
'гп ' => 0,
'гф ' => 0,
'гх' => 0,
'гх ' => 0,
'гц' => 0,
'гц ' => 0,
'гч ' => 0,
'гш ' => 0,
'гщ ' => 0,
'гъ' => 0,
'гъ ' => 0,
'гы ' => 0,
'гь' => 0,
'гь ' => 0,
'гэ ' => 0,
'гю' => 0,
'гю ' => 0,
'гя' => 0,
'гя ' => 0,
'дё ' => 0,
'дб ' => 0,
'дг ' => 0,
'дд ' => 0,
'дй' => 0,
'дй ' => 0,
'дк ' => 0,
'дм ' => 0,
'дн ' => 0,
'дп ' => 0,
'дс ' => 0,
'дф ' => 0,
'дх ' => 0,
'дц ' => 0,
'дч ' => 0,
'дш ' => 0,
'дщ ' => 0,
'дъ ' => 0,
'еа ' => 0,
'еу ' => 0,
'еъ' => 0,
'еъ ' => 0,
'еы' => 0,
'еы ' => 0,
'еь' => 0,
'еь ' => 0,
'еэ ' => 0,
'жё ' => 0,
'жв ' => 0,
'жг ' => 0,
'жж ' => 0,
'жз ' => 0,
'жй' => 0,
'жй ' => 0,
'жк ' => 0,
'жл ' => 0,
'жн ' => 0,
'жп ' => 0,
'жр ' => 0,
'жс ' => 0,
'жт ' => 0,
'жф ' => 0,
'жх ' => 0,
'жц ' => 0,
'жч ' => 0,
'жш' => 0,
'жш ' => 0,
'жщ' => 0,
'жщ ' => 0,
'жъ' => 0,
'жъ ' => 0,
'жы ' => 0,
'жэ ' => 0,
'жю' => 0,
'жю ' => 0,
'жя' => 0,
'жя ' => 0,
'зё ' => 0,
'зж ' => 0,
'зз ' => 0,
'зй' => 0,
'зй ' => 0,
'зк ' => 0,
'зп ' => 0,
'зр ' => 0,
'зс ' => 0,
'зт ' => 0,
'зф' => 0,
'зф ' => 0,
'зх' => 0,
'зх ' => 0,
'зц ' => 0,
'зч ' => 0,
'зш ' => 0,
'зщ' => 0,
'зщ ' => 0,
'зъ ' => 0,
'зэ ' => 0,
'иъ' => 0,
'иъ ' => 0,
'иы' => 0,
'иы ' => 0,
'иь' => 0,
'иь ' => 0,
'иэ ' => 0,
'йё' => 0,
'йё ' => 0,
'йа ' => 0,
'йв ' => 0,
'йг ' => 0,
'йж' => 0,
'йж ' => 0,
'йз ' => 0,
'йи ' => 0,
'йй' => 0,
'йй ' => 0,
'йо ' => 0,
'йу' => 0,
'йу ' => 0,
'йч ' => 0,
'йш ' => 0,
'йщ ' => 0,
'йъ' => 0,
'йъ ' => 0,
'йы' => 0,
'йы ' => 0,
'йь' => 0,
'йь ' => 0,
'йэ' => 0,
'йэ ' => 0,
'йю' => 0,
'йю ' => 0,
'йя' => 0,
'кё ' => 0,
'кб ' => 0,
'кг ' => 0,
'кд ' => 0,
'кж ' => 0,
'кз ' => 0,
'кй' => 0,
'кй ' => 0,
'км ' => 0,
'кн ' => 0,
'кф ' => 0,
'кц ' => 0,
'кч ' => 0,
'кш ' => 0,
'кщ' => 0,
'кщ ' => 0,
'къ' => 0,
'къ ' => 0,
'кы ' => 0,
'кь ' => 0,
'кэ' => 0,
'кэ ' => 0,
'кя' => 0,
'кя ' => 0,
'лв ' => 0,
'лж ' => 0,
'лз ' => 0,
'лй' => 0,
'лй ' => 0,
'лр ' => 0,
'лф ' => 0,
'лх ' => 0,
'лц ' => 0,
'лч ' => 0,
'лш ' => 0,
'лщ ' => 0,
'лъ' => 0,
'лъ ' => 0,
'лэ' => 0,
'лэ ' => 0,
'мё ' => 0,
'мв ' => 0,
'мг ' => 0,
'мд ' => 0,
'мз ' => 0,
'мй' => 0,
'мк ' => 0,
'мл ' => 0,
'мр ' => 0,
'мх ' => 0,
'мц ' => 0,
'мч ' => 0,
'мш ' => 0,
'мщ ' => 0,
'мъ' => 0,
'мъ ' => 0,
'мэ ' => 0,
'мю ' => 0,
'нё ' => 0,
'нб ' => 0,
'нв ' => 0,
'нй' => 0,
'нл ' => 0,
'нп ' => 0,
'нщ ' => 0,
'нъ ' => 0,
'нэ ' => 0,
'оъ' => 0,
'оъ ' => 0,
'оы' => 0,
'оы ' => 0,
'оь' => 0,
'оь ' => 0,
'пё ' => 0,
'пб ' => 0,
'пв' => 0,
'пв ' => 0,
'пг' => 0,
'пг ' => 0,
'пд ' => 0,
'пж' => 0,
'пж ' => 0,
'пз' => 0,
'пз ' => 0,
'пй' => 0,
'пй ' => 0,
'пк ' => 0,
'пл ' => 0,
'пм ' => 0,
'пн ' => 0,
'пф ' => 0,
'пх ' => 0,
'пц ' => 0,
'пч ' => 0,
'пш ' => 0,
'пщ ' => 0,
'пъ' => 0,
'пъ ' => 0,
'пэ' => 0,
'пэ ' => 0,
'пю ' => 0,
'рё ' => 0,
'рй' => 0,
'рй ' => 0,
'ръ' => 0,
'ръ ' => 0,
'рэ ' => 0,
'сб ' => 0,
'св ' => 0,
'сг ' => 0,
'сд ' => 0,
'сж ' => 0,
'сз' => 0,
'сз ' => 0,
'сй' => 0,
'сй ' => 0,
'сн ' => 0,
'сп ' => 0,
'сф ' => 0,
'сц ' => 0,
'сч ' => 0,
'сш ' => 0,
'сщ ' => 0,
'съ ' => 0,
'сэ ' => 0,
'тб ' => 0,
'тг ' => 0,
'тд ' => 0,
'тж ' => 0,
'тз ' => 0,
'тй' => 0,
'тй ' => 0,
'тк ' => 0,
'тл ' => 0,
'тп ' => 0,
'тф ' => 0,
'тх ' => 0,
'тц ' => 0,
'тш ' => 0,
'тщ ' => 0,
'тъ ' => 0,
'уё ' => 0,
'уо ' => 0,
'уу ' => 0,
'уц ' => 0,
'уъ' => 0,
'уъ ' => 0,
'уы' => 0,
'уы ' => 0,
'уь' => 0,
'уь ' => 0,
'уэ ' => 0,
'фё ' => 0,
'фб ' => 0,
'фв ' => 0,
'фг ' => 0,
'фд ' => 0,
'фж' => 0,
'фж ' => 0,
'фз' => 0,
'фз ' => 0,
'фй' => 0,
'фй ' => 0,
'фк ' => 0,
'фл ' => 0,
'фн ' => 0,
'фп' => 0,
'фп ' => 0,
'фс ' => 0,
'фх' => 0,
'фх ' => 0,
'фц' => 0,
'фц ' => 0,
'фч ' => 0,
'фш ' => 0,
'фщ ' => 0,
'фъ' => 0,
'фъ ' => 0,
'фэ' => 0,
'фэ ' => 0,
'фю ' => 0,
'хё' => 0,
'хё ' => 0,
'хб ' => 0,
'хг ' => 0,
'хд ' => 0,
'хж ' => 0,
'хз ' => 0,
'хй' => 0,
'хй ' => 0,
'хк ' => 0,
'хн ' => 0,
'хп ' => 0,
'хр ' => 0,
'хс ' => 0,
'хф ' => 0,
'хх ' => 0,
'хц ' => 0,
'хч ' => 0,
'хш ' => 0,
'хщ' => 0,
'хщ ' => 0,
'хъ ' => 0,
'хы' => 0,
'хы ' => 0,
'хь' => 0,
'хь ' => 0,
'хэ ' => 0,
'хю' => 0,
'хю ' => 0,
'хя' => 0,
'хя ' => 0,
'цё' => 0,
'цё ' => 0,
'цб' => 0,
'цб ' => 0,
'цв ' => 0,
'цг ' => 0,
'цд ' => 0,
'цж' => 0,
'цж ' => 0,
'цз ' => 0,
'цй' => 0,
'цй ' => 0,
'цк ' => 0,
'цл ' => 0,
'цм ' => 0,
'цн ' => 0,
'цп ' => 0,
'цр ' => 0,
'цс ' => 0,
'цт ' => 0,
'цф' => 0,
'цф ' => 0,
'цх' => 0,
'цх ' => 0,
'цц ' => 0,
'цч' => 0,
'цч ' => 0,
'цш ' => 0,
'цщ' => 0,
'цщ ' => 0,
'цъ' => 0,
'цъ ' => 0,
'ць' => 0,
'ць ' => 0,
'цэ' => 0,
'цэ ' => 0,
'цю' => 0,
'цю ' => 0,
'ця' => 0,
'ця ' => 0,
'чё ' => 0,
'чб ' => 0,
'чг' => 0,
'чг ' => 0,
'чд' => 0,
'чд ' => 0,
'чж ' => 0,
'чз' => 0,
'чз ' => 0,
'чй' => 0,
'чй ' => 0,
'чк ' => 0,
'чл ' => 0,
'чм ' => 0,
'чн ' => 0,
'чп' => 0,
'чп ' => 0,
'чр ' => 0,
'чс ' => 0,
'чф' => 0,
'чф ' => 0,
'чх ' => 0,
'чц ' => 0,
'чч ' => 0,
'чш ' => 0,
'чщ' => 0,
'чщ ' => 0,
'чъ' => 0,
'чъ ' => 0,
'чы' => 0,
'чы ' => 0,
'чэ' => 0,
'чэ ' => 0,
'чю' => 0,
'чю ' => 0,
'чя' => 0,
'чя ' => 0,
'шё ' => 0,
'шб ' => 0,
'шг ' => 0,
'шд' => 0,
'шд ' => 0,
'шж' => 0,
'шж ' => 0,
'шз' => 0,
'шз ' => 0,
'шй' => 0,
'шй ' => 0,
'шк ' => 0,
'шл ' => 0,
'шм ' => 0,
'шн ' => 0,
'шп ' => 0,
'шр ' => 0,
'шс ' => 0,
'шф ' => 0,
'шх' => 0,
'шх ' => 0,
'шч ' => 0,
'шш' => 0,
'шш ' => 0,
'шщ' => 0,
'шщ ' => 0,
'шъ' => 0,
'шъ ' => 0,
'шы' => 0,
'шы ' => 0,
'шэ' => 0,
'шэ ' => 0,
'шя' => 0,
'шя ' => 0,
'щб' => 0,
'щб ' => 0,
'щв ' => 0,
'щг' => 0,
'щг ' => 0,
'щд' => 0,
'щд ' => 0,
'щж' => 0,
'щж ' => 0,
'щз' => 0,
'щз ' => 0,
'щй' => 0,
'щй ' => 0,
'щк' => 0,
'щк ' => 0,
'щл' => 0,
'щл ' => 0,
'щм ' => 0,
'щн ' => 0,
'щп' => 0,
'щп ' => 0,
'щр ' => 0,
'щс' => 0,
'щс ' => 0,
'щт' => 0,
'щт ' => 0,
'щф' => 0,
'щф ' => 0,
'щх' => 0,
'щх ' => 0,
'щц' => 0,
'щц ' => 0,
'щч' => 0,
'щч ' => 0,
'щш' => 0,
'щш ' => 0,
'щщ' => 0,
'щщ ' => 0,
'щъ' => 0,
'щъ ' => 0,
'щы' => 0,
'щы ' => 0,
'щэ' => 0,
'щэ ' => 0,
'щю' => 0,
'щю ' => 0,
'щя' => 0,
'щя ' => 0,
'ъё ' => 0,
'ъа' => 0,
'ъа ' => 0,
'ъб' => 0,
'ъб ' => 0,
'ъв' => 0,
'ъв ' => 0,
'ъг' => 0,
'ъг ' => 0,
'ъд' => 0,
'ъд ' => 0,
'ъе ' => 0,
'ъж' => 0,
'ъж ' => 0,
'ъз' => 0,
'ъз ' => 0,
'ъи' => 0,
'ъи ' => 0,
'ъй' => 0,
'ъй ' => 0,
'ък' => 0,
'ък ' => 0,
'ъл' => 0,
'ъл ' => 0,
'ъм' => 0,
'ъм ' => 0,
'ън' => 0,
'ън ' => 0,
'ъо' => 0,
'ъо ' => 0,
'ъп' => 0,
'ъп ' => 0,
'ър' => 0,
'ър ' => 0,
'ъс' => 0,
'ъс ' => 0,
'ът' => 0,
'ът ' => 0,
'ъу' => 0,
'ъу ' => 0,
'ъф' => 0,
'ъф ' => 0,
'ъх' => 0,
'ъх ' => 0,
'ъц' => 0,
'ъц ' => 0,
'ъч' => 0,
'ъч ' => 0,
'ъш' => 0,
'ъш ' => 0,
'ъщ' => 0,
'ъщ ' => 0,
'ъъ' => 0,
'ъъ ' => 0,
'ъы' => 0,
'ъы ' => 0,
'ъь' => 0,
'ъь ' => 0,
'ъэ' => 0,
'ъэ ' => 0,
'ъю ' => 0,
'ъя ' => 0,
'ыё' => 0,
'ыё ' => 0,
'ыа' => 0,
'ыа ' => 0,
'ыи ' => 0,
'ыо ' => 0,
'ыу ' => 0,
'ыф ' => 0,
'ыъ' => 0,
'ыъ ' => 0,
'ыы' => 0,
'ыы ' => 0,
'ыь' => 0,
'ыь ' => 0,
'ыэ' => 0,
'ыэ ' => 0,
'ыю ' => 0,
'ьа' => 0,
'ьа ' => 0,
'ьв ' => 0,
'ьг ' => 0,
'ьж ' => 0,
'ьз ' => 0,
'ьй' => 0,
'ьй ' => 0,
'ьл ' => 0,
'ьн ' => 0,
'ьр ' => 0,
'ьу' => 0,
'ьу ' => 0,
'ьх ' => 0,
'ьщ ' => 0,
'ьъ' => 0,
'ьъ ' => 0,
'ьы ' => 0,
'ьь' => 0,
'ьь ' => 0,
'ьэ ' => 0,
'эё' => 0,
'эё ' => 0,
'эа' => 0,
'эа ' => 0,
'эб' => 0,
'эб ' => 0,
'эв ' => 0,
'эг ' => 0,
'эд ' => 0,
'эе' => 0,
'эе ' => 0,
'эж' => 0,
'эж ' => 0,
'эз ' => 0,
'эи ' => 0,
'эй ' => 0,
'эл ' => 0,
'эм ' => 0,
'эн ' => 0,
'эо' => 0,
'эо ' => 0,
'эу' => 0,
'эу ' => 0,
'эф ' => 0,
'эх ' => 0,
'эц' => 0,
'эц ' => 0,
'эч' => 0,
'эч ' => 0,
'эш ' => 0,
'эщ' => 0,
'эщ ' => 0,
'эъ' => 0,
'эъ ' => 0,
'эы' => 0,
'эы ' => 0,
'эь' => 0,
'эь ' => 0,
'ээ ' => 0,
'эю' => 0,
'эю ' => 0,
'эя' => 0,
'эя ' => 0,
'юё' => 0,
'юё ' => 0,
'юа ' => 0,
'юе ' => 0,
'юж ' => 0,
'юи ' => 0,
'юл ' => 0,
'юо ' => 0,
'юу' => 0,
'юу ' => 0,
'юц ' => 0,
'юъ' => 0,
'юъ ' => 0,
'юы' => 0,
'юы ' => 0,
'юь' => 0,
'юь ' => 0,
'юэ ' => 0,
'юя' => 0,
'яё' => 0,
'яё ' => 0,
'яа' => 0,
'яа ' => 0,
'яе ' => 0,
'яо ' => 0,
'яф' => 0,
'яф ' => 0,
'яъ' => 0,
'яъ ' => 0,
'яы' => 0,
'яы ' => 0,
'яь' => 0,
'яь ' => 0,
'яэ' => 0,
'яэ ' => 0,
#en
' \'f' => 0,
' \'p' => 0,
' \'q' => 0,
' \'r' => 0,
' \'x' => 0,
' \'y' => 0,
' \'z' => 0,
' bj' => 0,
' bq' => 0,
' bz' => 0,
' c\'' => 0,
' cq' => 0,
' cv' => 0,
' cx' => 0,
' dq' => 0,
' dx' => 0,
' ez' => 0,
' f\'' => 0,
' fh' => 0,
' fk' => 0,
' fq' => 0,
' fv' => 0,
' fw' => 0,
' fz' => 0,
' g\'' => 0,
' gf' => 0,
' gg' => 0,
' gj' => 0,
' gv' => 0,
' gx' => 0,
' gz' => 0,
' h\'' => 0,
' hj' => 0,
' hk' => 0,
' hn' => 0,
' hq' => 0,
' hx' => 0,
' iq' => 0,
' iw' => 0,
' iy' => 0,
' jb' => 0,
' jf' => 0,
' jh' => 0,
' jj' => 0,
' jk' => 0,
' jl' => 0,
' jm' => 0,
' jq' => 0,
' jw' => 0,
' jx' => 0,
' jy' => 0,
' jz' => 0,
' k\'' => 0,
' kf' => 0,
' kj' => 0,
' kq' => 0,
' kt' => 0,
' kx' => 0,
' kz' => 0,
' lj' => 0,
' lk' => 0,
' lq' => 0,
' lv' => 0,
' mj' => 0,
' mq' => 0,
' mz' => 0,
' nj' => 0,
' nk' => 0,
' nq' => 0,
' nz' => 0,
' oq' => 0,
' pj' => 0,
' pz' => 0,
' qb' => 0,
' qe' => 0,
' qf' => 0,
' qg' => 0,
' qh' => 0,
' qj' => 0,
' qk' => 0,
' qo' => 0,
' qp' => 0,
' qs' => 0,
' qv' => 0,
' qx' => 0,
' qy' => 0,
' qz' => 0,
' rb' => 0,
' rk' => 0,
' rq' => 0,
' rv' => 0,
' rx' => 0,
' rz' => 0,
' sz' => 0,
' tf' => 0,
' tg' => 0,
' tj' => 0,
' tq' => 0,
' u\'' => 0,
' ue' => 0,
' uj' => 0,
' uo' => 0,
' uq' => 0,
' uu' => 0,
' uy' => 0,
' vb' => 0,
' vj' => 0,
' vk' => 0,
' vn' => 0,
' vq' => 0,
' vr' => 0,
' vv' => 0,
' vw' => 0,
' vx' => 0,
' vy' => 0,
' vz' => 0,
' wj' => 0,
' wl' => 0,
' wn' => 0,
' wq' => 0,
' wx' => 0,
' wz' => 0,
' xb' => 0,
' xf' => 0,
' xg' => 0,
' xh' => 0,
' xj' => 0,
' xk' => 0,
' xq' => 0,
' xt' => 0,
' xu' => 0,
' xz' => 0,
' yf' => 0,
' yg' => 0,
' yh' => 0,
' yj' => 0,
' yk' => 0,
' yl' => 0,
' yn' => 0,
' yq' => 0,
' yv' => 0,
' yx' => 0,
' yy' => 0,
' yz' => 0,
' z\'' => 0,
' zb' => 0,
' zc' => 0,
' zd' => 0,
' zf' => 0,
' zg' => 0,
' zh' => 0,
' zj' => 0,
' zk' => 0,
' zl' => 0,
' zm' => 0,
' zq' => 0,
' zr' => 0,
' zv' => 0,
' zw' => 0,
' zx' => 0,
' zz' => 0,
'\'a ' => 0,
'\'b' => 0,
'\'b ' => 0,
'\'c ' => 0,
'\'f' => 0,
'\'f ' => 0,
'\'g' => 0,
'\'g ' => 0,
'\'h ' => 0,
'\'i ' => 0,
'\'j' => 0,
'\'j ' => 0,
'\'k' => 0,
'\'k ' => 0,
'\'l ' => 0,
'\'n ' => 0,
'\'o ' => 0,
'\'p ' => 0,
'\'q' => 0,
'\'q ' => 0,
'\'r ' => 0,
'\'u' => 0,
'\'u ' => 0,
'\'v ' => 0,
'\'w ' => 0,
'\'x' => 0,
'\'x ' => 0,
'\'z' => 0,
'\'z ' => 0,
'b\' ' => 0,
'bg ' => 0,
'bh ' => 0,
'bp ' => 0,
'bq' => 0,
'bq ' => 0,
'bv ' => 0,
'bx' => 0,
'bz' => 0,
'bz ' => 0,
'c\' ' => 0,
'cf ' => 0,
'cj' => 0,
'cn ' => 0,
'cq ' => 0,
'cv' => 0,
'cw' => 0,
'cx' => 0,
'cx ' => 0,
'cz ' => 0,
'db ' => 0,
'dj ' => 0,
'dk ' => 0,
'dw ' => 0,
'dx' => 0,
'eh ' => 0,
'ej ' => 0,
'f\' ' => 0,
'fg ' => 0,
'fh ' => 0,
'fj' => 0,
'fj ' => 0,
'fk' => 0,
'fk ' => 0,
'fq' => 0,
'fq ' => 0,
'fv ' => 0,
'fw ' => 0,
'fx' => 0,
'fx ' => 0,
'fz' => 0,
'fz ' => 0,
'g\' ' => 0,
'gc ' => 0,
'gf ' => 0,
'gj ' => 0,
'gk ' => 0,
'gl ' => 0,
'gq' => 0,
'gq ' => 0,
'gv' => 0,
'gv ' => 0,
'gw ' => 0,
'gx' => 0,
'gx ' => 0,
'gz ' => 0,
'hb ' => 0,
'hc ' => 0,
'hg ' => 0,
'hh ' => 0,
'hj' => 0,
'hj ' => 0,
'hk ' => 0,
'hv' => 0,
'hv ' => 0,
'hw ' => 0,
'hx' => 0,
'hx ' => 0,
'hz' => 0,
'i\' ' => 0,
'ih ' => 0,
'iq ' => 0,
'iw ' => 0,
'j\'' => 0,
'j\' ' => 0,
'jb' => 0,
'jb ' => 0,
'jc' => 0,
'jc ' => 0,
'jd' => 0,
'jf' => 0,
'jg' => 0,
'jg ' => 0,
'jh' => 0,
'jh ' => 0,
'jj' => 0,
'jj ' => 0,
'jk ' => 0,
'jl ' => 0,
'jm' => 0,
'jm ' => 0,
'jn' => 0,
'jn ' => 0,
'jp ' => 0,
'jq' => 0,
'jq ' => 0,
'jr' => 0,
'jr ' => 0,
'js' => 0,
'js ' => 0,
'jt' => 0,
'ju ' => 0,
'jv' => 0,
'jv ' => 0,
'jw' => 0,
'jw ' => 0,
'jx' => 0,
'jx ' => 0,
'jy' => 0,
'jy ' => 0,
'jz' => 0,
'jz ' => 0,
'kb ' => 0,
'kc ' => 0,
'kd ' => 0,
'kj ' => 0,
'km ' => 0,
'kp ' => 0,
'kq' => 0,
'kq ' => 0,
'kv' => 0,
'kv ' => 0,
'kx' => 0,
'kx ' => 0,
'kz' => 0,
'kz ' => 0,
'lg ' => 0,
'lh ' => 0,
'lj ' => 0,
'lq ' => 0,
'lr ' => 0,
'lv ' => 0,
'lw ' => 0,
'lx' => 0,
'lz ' => 0,
'm\' ' => 0,
'mg ' => 0,
'mh ' => 0,
'mj ' => 0,
'mk ' => 0,
'mq' => 0,
'mq ' => 0,
'mx' => 0,
'mx ' => 0,
'mz' => 0,
'nb ' => 0,
'nm ' => 0,
'pj ' => 0,
'pk ' => 0,
'pq' => 0,
'pq ' => 0,
'pv' => 0,
'pw ' => 0,
'px' => 0,
'px ' => 0,
'pz ' => 0,
'q\'' => 0,
'q\' ' => 0,
'qa ' => 0,
'qb' => 0,
'qb ' => 0,
'qc' => 0,
'qc ' => 0,
'qd' => 0,
'qd ' => 0,
'qe' => 0,
'qe ' => 0,
'qf' => 0,
'qf ' => 0,
'qg' => 0,
'qg ' => 0,
'qh' => 0,
'qh ' => 0,
'qi' => 0,
'qj' => 0,
'qj ' => 0,
'qk' => 0,
'qk ' => 0,
'ql' => 0,
'ql ' => 0,
'qm' => 0,
'qm ' => 0,
'qn' => 0,
'qn ' => 0,
'qo' => 0,
'qo ' => 0,
'qp' => 0,
'qp ' => 0,
'qq' => 0,
'qq ' => 0,
'qr' => 0,
'qs' => 0,
'qs ' => 0,
'qt' => 0,
'qt ' => 0,
'qu ' => 0,
'qv' => 0,
'qv ' => 0,
'qw' => 0,
'qw ' => 0,
'qx' => 0,
'qx ' => 0,
'qy' => 0,
'qy ' => 0,
'qz' => 0,
'qz ' => 0,
'rq ' => 0,
'rz ' => 0,
'rf ' => 0,
'rb ' => 0,
'sg ' => 0,
'sj ' => 0,
'sx' => 0,
'sx ' => 0,
'sz' => 0,
'sz ' => 0,
'tc ' => 0,
'tg ' => 0,
'tj ' => 0,
'tq' => 0,
'tq ' => 0,
'tx' => 0,
'tx ' => 0,
'uj ' => 0,
'uq ' => 0,
'uu ' => 0,
'uw ' => 0,
'v\' ' => 0,
'vb' => 0,
'vb ' => 0,
'vc' => 0,
'vf' => 0,
'vf ' => 0,
'vg' => 0,
'vh' => 0,
'vh ' => 0,
'vj' => 0,
'vj ' => 0,
'vk' => 0,
'vk ' => 0,
'vl ' => 0,
'vm' => 0,
'vn ' => 0,
'vp' => 0,
'vp ' => 0,
'vq' => 0,
'vq ' => 0,
'vr ' => 0,
'vv ' => 0,
'vw' => 0,
'vw ' => 0,
'vx' => 0,
'vz' => 0,
'vz ' => 0,
'w\' ' => 0,
'wb ' => 0,
'wc ' => 0,
'wf ' => 0,
'wg ' => 0,
'wj' => 0,
'wj ' => 0,
'wq' => 0,
'wq ' => 0,
'wr ' => 0,
'wv' => 0,
'wv ' => 0,
'wx' => 0,
'wz ' => 0,
'x\'' => 0,
'x\' ' => 0,
'xa ' => 0,
'xb ' => 0,
'xc ' => 0,
'xd' => 0,
'xd ' => 0,
'xf ' => 0,
'xg ' => 0,
'xh ' => 0,
'xj' => 0,
'xj ' => 0,
'xk' => 0,
'xk ' => 0,
'xl ' => 0,
'xm ' => 0,
'xn' => 0,
'xn ' => 0,
'xp ' => 0,
'xq ' => 0,
'xr' => 0,
'xr ' => 0,
'xs ' => 0,
'xu ' => 0,
'xv' => 0,
'xv ' => 0,
'xw ' => 0,
'xx' => 0,
'xz' => 0,
'xz ' => 0,
'yb ' => 0,
'yc ' => 0,
'yd ' => 0,
'yf ' => 0,
'yg ' => 0,
'yh ' => 0,
'yj ' => 0,
'yq' => 0,
'yq ' => 0,
'yu ' => 0,
'yv ' => 0,
'yw ' => 0,
'yy' => 0,
'yy ' => 0,
'yz ' => 0,
'z\'' => 0,
'z\' ' => 0,
'zb ' => 0,
'zc' => 0,
'zc ' => 0,
'zd' => 0,
'zd ' => 0,
'zf' => 0,
'zf ' => 0,
'zg ' => 0,
'zh' => 0,
'zh ' => 0,
'zj' => 0,
'zj ' => 0,
'zk ' => 0,
'zl ' => 0,
'zn' => 0,
'zn ' => 0,
'zp ' => 0,
'zq' => 0,
'zq ' => 0,
'zr' => 0,
'zr ' => 0,
'zs' => 0,
'zs ' => 0,
'zt' => 0,
'zt ' => 0,
'zu ' => 0,
'zv ' => 0,
'zw ' => 0,
'zx' => 0,
'zx ' => 0,
);
/**
*
* @param array|null $words_exceptions
*/
public function __construct(array $words_exceptions = null)
{
if (! ReflectionTypeHint::isValid()) return false;
#русский --> английский:
$this->en_correct = '/(?: (?:' . $this->tt_f . ')
(?: (?:' . $this->en_uniq . ') | (?:' . $this->en_sc . '){2} )
| (?:' . $this->en_sc . ')
(?:' . $this->tt_f . ')
(?:' . $this->en_sc . ')
| (?: (?:' . $this->en_uniq . ') | (?:' . $this->en_sc . '){2} )
(?:' . $this->tt_f . ')
)
/sxSX';
#английский --> русский:
$this->tt_correct = '/(?: (?:' . $this->en_sc . ')
(?: (?:' . $this->tt_uniq . ') | (?:' . $this->tt_f . '){2} )
| (?:' . $this->tt_f . ')
(?:' . $this->en_sc . ')
(?:' . $this->tt_f . ')
| (?: (?:' . $this->tt_uniq . ') | (?:' . $this->tt_f . '){2} )
(?:' . $this->en_sc . ')
)
/sxSX';
$this->table_flip = array(
0 => array_flip($this->table[0]),
1 => array_flip($this->table[1]),
);
if (is_array($words_exceptions)) $this->words_exceptions += $words_exceptions;
}
/**
* Исправляет клавиатурные опечатки в тексте.
*
* @param scalar|null $s Текст в кодировке UTF-8.
* @param int $mode Константы self::SIMILAR_CHARS и/или self::KEYBOARD_LAYOUT,
* (их можно комбинировать). Описание констант см. выше.
* При использовании self::KEYBOARD_LAYOUT время работы увеличивается примерно в 10 раз.
* @param array &$words Ассоц. массив со словами, которые были исправлены:
* в ключах оригиналы, в значениях исправленные слова.
* @return string|bool Returns FALSE if error occured
*/
public function parse($s, $mode = self::SIMILAR_CHARS, array &$words = null)
{
if (! ReflectionTypeHint::isValid()) return false;
if (! is_string($s)) return $s;
if ($mode < self::SIMILAR_CHARS || $mode > (self::SIMILAR_CHARS | self::KEYBOARD_LAYOUT | self::ADD_FIX))
{
trigger_error('Unknown mode', E_USER_WARNING);
return false;
}
$this->mode = $mode;
#вырезаем и заменяем некоторые символы
$additional_chars = array(
"\xc2\xad", #"мягкие" переносы строк (&shy;)
);
#http://ru.wikipedia.org/wiki/Диакритические_знаки
$s = UTF8::diactrical_remove($s, $additional_chars, $is_can_restored = true, $restore_table);
$this->words = array();
$s = $this->_parse1($s);
$s = $this->_parse2($s);
$s = UTF8::diactrical_restore($s, $restore_table);
$words = $this->words;
return $s;
}
private function _parse1($s)
{
#заменяем слова из текста, минимальная длина -- 3 символа, меньше нельзя
return preg_replace_callback('/(?> (' . $this->en . ') #1 латинские буквы
| (' . $this->tt . ') #2 русские буквы
| (' . $this->sc . ') #3 символы, которые м.б. набраны по ошибке в английской раскладке клавиатуры вместо русских букв
){3,}+
/sxSX', array($this, '_word'), $s);
}
private function _parse2($s)
{
#исправляем русские буквы (похожие на латинские) с рядом стоящими цифрами на латинские
#например, это м. б. каталожные номера автозапчастей, в которых есть русские буквы: 1500A023, 52511-60900-H0, K2305, XA527672
#корректно обрабатываем вхождения '1-ое', 'Ту-134', 'А19-3107/06-43-Ф02-4227/06-С1'
if (version_compare(PHP_VERSION, '5.2.0', '<')) return $s;
return preg_replace_callback('~(?: (?<=[^-_/]|^)
(?:' . $this->ru_similar . ')++
(?= (?:' . $this->en . '|[-_/])*+ (?<=[^-_/]|' . $this->en . '[-_/])
\d [\d-_/]*+ (?!' . $this->tt_uniq . ')
)
| (?<=[^-_/]|^)
\d (?:' . $this->en . '|[-_/])*+ (?<=[^-_/]|' . $this->en . '[-_/])
\K
(?:' . $this->ru_similar . ')++
(?= [\d-_/]*+ (?!' . $this->tt_uniq . ') )
)
~sxSX', array($this, '_entry'), $s);
}
private function _entry(array &$a)
{
$entry =& $a[0];
$s = strtr($entry, $this->table[0]);
if ($s !== $entry) $this->words[$entry] = $s;
return $s;
}
private function _word(array &$a)
{
$word = $a[0];
#var_export($a);
// todo: add skip list
if ($word === 'блэкаут')
{
return $word;
}
$suggestions = array();
#если найдено слово из мешанины русских и латинских букв
if (! empty($a[1]) && ! empty($a[2]))
{
if (($this->mode & self::SIMILAR_CHARS) === 0) return $word;
#ВНИМАНИЕ! порядок следования правил преобразования имеет значение!
/*
Исправляем ошибочно набранные буквы, которые выглядят одинаково
в инициалах перед фамилиями (русский <--> английский), например: Т.С.Навка
*/
#0a. английский --> русский:
if (substr($word, 1, 1) === '.' #оптимизация
&& preg_match('/^ ( ' . $this->en_similar_uc . '\. #первый инициал
(?:' . $this->en_similar_uc . '\.)? #второй инициал (необязательно)
) #1 инициалы
(' . $this->no_sc . '{2,}+) #2 фамилия (английские и русские буквы)
$/sxSX', $word, $m))
{
$m[2] = $this->_parse1($m[2]);
#фамилия по-русски?
if (preg_match('/^ (?:' . $this->tt_uc . ') #первая буква д.б. большая
(?:' . $this->tt_f . ')+ #минимальное кол-во букв в фамилии = 2
$/sxSX', $m[2])) return strtr($m[1], $this->table_flip[0]) . $m[2];
}
#0b. русский --> английский:
if (substr($word, 2, 1) === '.' #оптимизация
&& preg_match('/^ ( ' . $this->ru_similar_uc . '\. #первый инициал
(?:' . $this->ru_similar_uc . '\.)? #второй инициал (необязательно)
) #1 инициалы
(' . $this->no_sc . '{2,}+) #2 фамилия (английские и русские буквы)
$/sxSX', $word, $m))
{
$m[2] = $this->_parse1($m[2]);
#фамилия по-англ.?
if (preg_match('/^ ' . $this->en_uc . ' #первая буква д.б. большая
' . $this->en . '++ #минимальное кол-во букв в фамилии = 2
$/sxSX', $m[2])) return strtr($m[1], $this->table[0]) . $m[2];
}
#1. английский --> русский:
$this->method = 0; #буквы, которые выглядят одинаково
$this->is_flip = true;
$s = $this->_replace($word, $this->tt_correct);
if ($word !== $s && ! $this->_is_mixed($s)) $suggestions['tt0'] = $s;
#2. английский --> русский:
$this->method = 1; #буквы в другой раскладке клавиатуры
$this->is_flip = true;
$s = $this->_replace($word, $this->tt_correct);
if ($word !== $s) $suggestions['tt1'] = $s;
#3. русский --> английский:
$this->method = 0; #буквы, которые выглядят одинаково
$this->is_flip = false;
$s = $this->_replace($word, $this->en_correct);
if ($word !== $s && ! $this->_is_mixed($s)) $suggestions['en0'] = $s;
#4. русский --> английский:
$this->method = 1; #буквы в другой раскладке клавиатуры
$this->is_flip = false;
$s = $this->_replace($word, $this->en_correct);
if ($word !== $s) $suggestions['en1'] = $s;
}
#если найдено слово только из латинских букв; минимальная длина -- 4 буквы!
elseif (! empty($a[1]) && strlen($word) >= 4)
{
if (($this->mode & self::KEYBOARD_LAYOUT) === 0) return $word;
#не обрабатываем аббревиатуры, пример: AMPAS
if (preg_match('/^(?:' . $this->en_uc . '|' . $this->sc . '){1,6}+$/sxSX', $word)) return $word;
#английский --> русский:
$suggestions['en1'] = $word;
$suggestions['tt1'] = strtr($word, $this->table_flip[1]);
}
#если найдено слово только из русских букв; минимальная длина -- 4 буквы!
elseif (! empty($a[2]) && strlen($word) >= 8)
{
if (($this->mode & self::KEYBOARD_LAYOUT) === 0) return $word;
#не обрабатываем аббревиатуры, пример: ДОСААФ
if (preg_match('/^(?:' . $this->tt_uc . '|' . $this->sc . '){1,6}+$/sxSX', $word)) return $word;
#русский --> английский:
$suggestions['tt1'] = $word;
$suggestions['en1'] = strtr($word, $this->table[1]);
}
#найдены спецсимволы или длина слова слишком мала
else return $word;
$suggestions = array_unique($suggestions);
#var_export($suggestions);
$c = count($suggestions);
if ($c === 0) $s = $word;
else $s = $this->_detect($word, $suggestions, ! empty($a[3]));
if ($s !== $word)
{
$this->words[$word] = $s;
if ($this->mode >= (self::KEYBOARD_LAYOUT | self::ADD_FIX)) $s = '(' . $word . '=>' . $s . ')';
}
return $s;
}
private function _replace($word, $regexp)
{
do $word = preg_replace_callback($regexp, array(&$this, '_strtr'), $w = $word);
while ($w !== $word);
return $word;
}
private function _strtr(array $a)
{
$word =& $a[0];
return strtr($word, $this->is_flip ? $this->table_flip[$this->method] : $this->table[$this->method]);
}
private function _is_mixed($word)
{
return preg_match('/(?:' . $this->en . ')/sxSX', $word) &&
preg_match('/(?:' . $this->tt_f . ')/sxSX', $word);
}
#выбираем из нескольких вариантов один
private function _detect($word, array $suggestions, $is_sc)
{
if (0) #DEBUG
{
//$suggestions['?'] = $word;
//var_export($suggestions);
}
#не д. б. несуществующих N-грамм
foreach ($suggestions as $type => $w)
{
$lang = substr($type, 0, 2);
if ($this->_bigram_exists($w, $lang)) unset($suggestions[$type]);
}
if (0) #DEBUG
{
//$suggestions['?'] = $word;
//var_export($suggestions);
}
if (count($suggestions) === 0) return $word;
$s = end($suggestions);
#если в $word были спецсимволы, а в $s их уже нет, возвращаем $s
if ($is_sc && ! preg_match('/' . $this->sc . '/sSX', $s)) return $s;
#если в $s спецсимволов больше чем букв, возвращаем $word
$sc_count = 0;
$s = preg_replace('/' . $this->sc . '/sSX', '', $s, -1, $sc_count);
if ($sc_count > 0 && $sc_count > UTF8::strlen($s)) return $word;
return reset($suggestions);
}
#анализ на основе N-грамм русского и английского языка
private function _bigram_exists($word, $lang)
{
$word = ($lang === 'en') ? strtolower($word) : UTF8::lowercase($word);
#шаг 0.
#проверяем слова в списке слов-исключений
if (array_key_exists($word, $this->words_exceptions[$lang])) return false;
#шаг 1.
#проверка на 4 согласные буквы подряд; пример: больши{нств}о, юрисконсу{льтс}тво
if (preg_match('/(?:' . $this->consonant_lc[$lang] . '){4}/sxSX', $word, $m)
#проверяем список исключений
&& ! array_key_exists($m[0], $this->consonants4_lc[$lang])) return true;
#шаг 2.
#проверка на 3 гласные буквы подряд; пример: длиннош{еее}, зм{еео}бразный
if (preg_match('/(?:' . $this->vowel_lc[$lang] . '){3}/sxSX', $word, $m)
#проверяем список исключений
&& ! array_key_exists($m[0], $this->vowels3_lc[$lang])) return true;
#шаг 3.
$length = UTF8::strlen($word);
for ($pos = 0, $limit = $length - 1; $pos < $limit; $pos++)
{
/*
TODO Качество проверки по несуществующим биграммам можно немного повысить,
если учитывать не только начало и конец слова, но и все позиции биграмм в слове.
*/
$ss = UTF8::substr($word, $pos, 2);
if ($pos === 0) $ss = ' ' . $ss; #beginning of word
elseif ($pos === $limit - 1) $ss = $ss . ' '; #ending of word
if (array_key_exists($ss, $this->bigrams)) return true;
}
return false;
}
}