Список работ

Поддержка системы автоматической правки текста

Содержание

Введение

Приводятся описание таблиц базы данных (БД), встроенной в систему автоматической правки русского текста. Также приводятся программы формирования, заполнения и редактирования таблиц БД.
Работа с таблицами ведется в среде SQL Server. При поступлении новых данных таблицы, используемые при правке текста, пополняются.
Приложение разбора и правки текста реализовано на C#.
Таблицы БД делятся на три следующие группы:

Кроме того, имеется таблица freq, содержащая частотный словарь лемм русского языка.
Число записей в таблице равно 19803. В таблице два следующих поля:

Таблица используется в демонстрационной программе правки слов [1].
Также приводятся примеры, содержащихся в таблицах данных, и методические материалы по морфологическому и морфемному разбору слов [2-6].

Таблицы системы правки текста

Таблицы проверки и правки текста

Имя таблицыОписаниеПоляЧисло записей
all_words_distСловоформы без повторовcode, int
word, char(30)
2'450'676. Создана по данным таблицы all_words
neighborsТаблица слов-соседейcode, int
code_neighbor, int
neighbourhood, int
Постоянно пополняется в результате разборов новых текстов.
new_wordsТаблица новых слов (их нет в all_words_dist)code, int
word, char(30)
Постоянно пополняется в результате разборов новых текстов
word_delТаблица сокращенных словоформcode, int
word_del, char(30)
2'733'1576. Создана по данным таблицы all_words_dist

Таблицы морфологического разбора русских слов

Имя таблицыЧто содержитСокращениеЧисло записей Поля
adjectivesПрилагательныепрл856'128code, int
wcase, char(4)
gender, char(3)
short, bit
plural, bit
comp, char(5)
adverbsНаречиянар16'056code, char(18)
type_sub, char(5)
type_ssub, char(6)
vozv, bit
all_wordsВсе слова4'159'394code, int
codeParent, int
word, char(30)
type, char(8)
communionsПричастияпрч1'989'015code, int
wcase, char(4)
time, char(4)
transit, char(6)
perfect, bit
vozv, bit
plural, bit
gender, char(3)
nounsСуществительныесущ767'694code, int
plural, bit
gender, char(3)
wcase, char(4)
soul, bit
numeralsЧислительныечисл1'582code, int
type_sub, char(5)
wcase, char(4)
gender, char(3)
soul, bit
plural, bit
other_wordsВводные слова, Междометия, Местоимения,
Местоимения-наречия, Предикативы,
Союзы, Частицы
ввод, межд, мест,
нар,мест, предик,
союз, част
2'919code, int
participlesДеепричастиядееп56'120code, int
transit, char(6)
perfect, bit
time, char(4)
vozv, bit
pretextsПредлогипредл411code, int
wcase, char(4)
pronouns_aМестоимения-прилагательныепрл,мест1'485code, int
plural, bit
gender, char(3)
wcase, char(4)
soul, bit
pronouns_nМестоимения-существительныесущ,мест351code, int
plural, bit
gender, char(3)
wcase, char(4)
verbsГлаголыгл467'722code, int
gender, char(3)
transit, char(6)
perfect, bit
face, char(3)
nakl, char(3)
vozv, bit
kind, char(4)
plural, bit
inf, bit
time, char(4)

Большинство таблиц сформировано по данным таблицы words, содержащей морфологический словарь русского языка.
Таблица words создана по файлу, доступному на [7].
Файл содержит архив SQL скрипта морфологического словаря русского языка, составленного по словарю М. Хагена "Полная парадигма. Морфология".
Словарь включает 4'159'394 словоформ для 142'792 лемм.
Словарь составлен на основе файла "Полная акцентуированная парадигма по Зализняку" и существенно расширен за счет таких электронных словарей, как

Таблицы словообразования и морфемного разбора русских слов

Имя таблицыЧто содержитПоляЧисло записей
prefsПриставкиpref, char(7)109
suffsСуффиксыsuff, char(7)160
psuffsПостфиксыpsuf, char(7)8
rootsКорниroot, char(30) freq, smallint16'228
endsОкончанияend0, , char(3)16

Описание полей таблиц БД

Приведено в следующей таблице:

Имя поляОписание и значенияТип
typeЧасти речи: ввод, межд, мест, нар,мест, предик, предл, союз, част; гл, дееп,
нар, прл, прл,мест, прч, сущ, сущ,мест, числ
char(8)
codeКод словаint
code_neighborКод слова-соседа справаint
neighbourhoodЧисло соседстint
codeParentКод родительского словаint
wordСловоchar(30)
wcaseПадеж: им, род, дат, вин, тв, пр, мест, зват, парт, NULLchar(4)
genderРод: муж, жен, ср, NULLchar(3)
soulОдушевленность: 1, 0, NULLbit
compСравнительная форма: сравн, NULLchar(5)
shortПризнак краткой формы прилагательного: 1, 0, NULLbit
pluralМножественное число: 1, 0, NULLbit
transitПереходность: перех, непер, пер/не, NULLchar(6)
perfectСовершенная форма: 1, 0bit
infПризнак инфинитива: 1, 0, NULLbit
faceЛицо глагола: 1-е, 2-е, 3-е, безл, NULLchar(3)
naklНаклонение или залог глагола: пов, NULLchar(3)
kindВид глагола: 2вид, NULLchar(4)
vozvПризнак возвратной формы: 0, 1, NULLbit
timeВременная форма: наст, прош, буд, NULLchar(4)
type_subПодтип: неизм, опред, счет, поряд, обст, кол, собир, неопр, NULLchar(5)
type_ssubПодтипы наречий: кач, степ, спос, врем, места, напр, причин, цель, NULLchar(6)

Индексы таблиц БД

Приведены в следующей таблице:

Имя таблицыИмя индексаТип индекса
all_words_distcode;
word
Clustered (Primary key);
Unique, Non-Clustered
word_delwordDelNon-Unique, Clustered
neighborscode_code_neighbor;
code;
code_neighbor
Unique, Clustered;
Non-Unique, Clustered;
Non-Unique, Clustered
new_wordscodeUnique, Clustered

При необходимости индексы явно указываются в тексте запроса, например:

select code_neighbor, neighbourhood from neighbors with(index(code)) where code = @code

Примеры слов различных частей речи

Приведены в следующей таблице:

Часть речиКоличествоПримеры
Вводные слова210далее, дескать, кроме того
Предлоги411из-за, к, от, кроме
Междометия428баста, вот те на, полундра
Союзы322а, благодаря тому что, да и, ещё, и, что
Частицы488аж, ведь, да вот, так-с
Местоимения-существительные351аз, вот что, мы, то, я
Местоимения-прилагательные1'485любой, мои, никоим, одной
Местоимения-наречия72где, здесь, этак
Местоимения прочие8какой там, на то на се, мало что
Предикативы1'302ало, чудно, ша
Существительные767'694амулет, амулета, амулетам, амулетами, амулетах, амулете, амулетов, амулетом, амулету, амулеты
Глаголы467'722алкаем, алкает, алкаете, алкаешь, алкай, алкайте, алкал, алкала, алкали, алкало, алкать, алкаю, алкают
Прилагательные856'128травяной, травяного, травяному, травяным, травяном, травяная, травяную, травяною, травяное, травяные, травяных, травяными
Причастия1'989'015алкавшая, алкавшего, алкавшей, алкавшем, алкавшему, алкавшею, алкавший, алкавшим, алкавшую, алкаем, алкаема, алкаемая, алкаемы, алкаемого, алкаемое, алкаемой, алкаемом, алкаемому, алкаемою, алкаемые, алкаемый, алкаемым, алкаемыми, алкаемых
Деепричастия56'120адаптировав, адаптируя, адаптировавшись, адаптируясь
Наречия16'056аккурат, аккуратнее, аккуратней, аккуратненько, аккуратно
Числительные1'582шестая, шестеро, шестерым, шестерыми, шестерых, шести

Вспомогательные программы системы разборки и правки текстов

Создание таблицы, не содержащей повторы слов

Таблица all_words_dist, не содержащая повторы слов, создается на основе таблицы all_words, в которую перенес морфологический словарь русского языка.
При проверке текста считается, что слово написано с орфографической ошибкой, если его нет в таблице all_words_dist.
Таблица all_words_dist пополняется новыми проверенными словами при разборе надежных текстов. Сам же разбор выполняется с целью формирования таблицы соседей.
Наполнение all_words_dist обеспечивается следующим C#-кодом:

private void buttonDistinct_Click(object sender, EventArgs e)
        {
            string word;
            int code, i, k = 0;
            bool notEmpty = true;
            SqlDataReader readerWord, readerDist;
            SqlCommand commandWord, commandDist, commandDistAdd;
            SqlConnection conWord, conDist, conDistAdd;
            conWord = new SqlConnection("Data Source=HP-PC\\SQLEXPRESS;Initial Catalog=CrPr;Integrated Security=SSPI;");
            conDist = new SqlConnection("Data Source=HP-PC\\SQLEXPRESS;Initial Catalog=CrPr;Integrated Security=SSPI;");
            conDistAdd = new SqlConnection("Data Source=HP-PC\\SQLEXPRESS;Initial Catalog=CrPr;Integrated Security=SSPI;");
            //
            commandWord = new SqlCommand();
            commandWord.CommandType = CommandType.Text;
            commandWord.Connection = conWord;
            commandWord.Connection.Open();
            commandWord.CommandText = "select word, code from all_words";
            //
            commandDist = new SqlCommand();
            commandDist.CommandType = CommandType.Text;
            commandDist.Connection = conDist;
            commandDist.CommandText = "select word from all_words_dist where word = @word";
            commandDist.Parameters.Add("@word", SqlDbType.Char, 30);
            //
            commandDistAdd = new SqlCommand();
            commandDistAdd.CommandType = CommandType.Text;
            commandDistAdd.Connection = conDistAdd;
            commandDistAdd.CommandText = "insert into all_words_dist (word, code) values(@word, @code)";
            commandDistAdd.Parameters.Add("@word", SqlDbType.Char, 30);
            commandDistAdd.Parameters.Add("@code", SqlDbType.Int);
            //
            readerWord = commandWord.ExecuteReader();
            while (readerWord.Read())
            {
                word = readerWord.GetString(0).TrimEnd().ToLower();
                code = readerWord.GetInt32(1);
                commandDist.Parameters["@word"].Value = word;
                conDist.Open();
                readerDist = commandDist.ExecuteReader();
                notEmpty = readerDist.Read();
                conDist.Close();
                if (notEmpty) continue;
                commandDistAdd.Parameters["@word"].Value = word;
                commandDistAdd.Parameters["@code"].Value = code;
                conDistAdd.Open();
                commandDistAdd.ExecuteNonQuery();
                conDistAdd.Close();
                k++;
            }
            conWord.Close();
            MessageBox.Show("Добавлено в all_words_dist: " + k);
        }

Создание таблицы сокращенных слов

Имя создаваемой таблицы – word_del; имя таблицы-источника – all_words_dist.
В word_del помещаются сокращенные слова all_words_dist, получаемые в результате поочередного удаления символа текущего слова.
При правке текста, слово с ошибкой "пропускается" через таблицу word_del: поочередно удаляется каждый символ слова и выполняется поиск сокращенного слова в word_del. В случае удачи родитель сокращенного слова (он находится в таблице all_words_dist) заносится в таблицу кандидатов на замену ошибочно написанного слова.
Формирование word_del разделено на этапы: на каждом этапе обрабатываются слова all_words_dist, которые начинаются на заданную букву русского алфавита.
Создание word_del обеспечивается следующим C#-кодом:

        private void buttonDeleting_Click(object sender, EventArgs e)
        {
            string word, wordDel;
            string addr = "Data Source=HP-PC\\SQLEXPRESS;Initial Catalog=CrPr;Integrated Security=SSPI;";
            int code, i, k = 0, k2 = 0;
            bool found = true;
            SqlDataReader readerWordDel;
            SqlDataReader readerWord;
            SqlCommand commandWord, commandWordDel, commandWordDelAdd;
            SqlConnection conWord, conWordDel, conWordDelAdd;
            conWord = new SqlConnection(addr);
            conWordDel = new SqlConnection(addr);
            conWordDelAdd = new SqlConnection(addr);
            //
            commandWord = new SqlCommand();
            commandWord.CommandType = CommandType.Text;
            commandWord.Connection = conWord;
            commandWord.Connection.Open();
            // Выбираем слова, которые начинаются на указанную букву 'а', 'б' и т. д.
            commandWord.CommandText = "select word, code from all_words_dist where left(word, 1) = 'а'";
            //
            commandWordDel = new SqlCommand();
            commandWordDel.CommandType = CommandType.Text;
            commandWordDel.Connection = conWordDel;
            commandWordDel.CommandText = "select wordDel from word_del where wordDel = @wordDel and code = @code";
            commandWordDel.Parameters.Add("@code", SqlDbType.Int);
            commandWordDel.Parameters.Add("@wordDel", SqlDbType.Char, 30);
            //
            commandWordDelAdd = new SqlCommand();
            commandWordDelAdd.CommandType = CommandType.Text;
            commandWordDelAdd.Connection = conWordDelAdd;
            commandWordDelAdd.CommandText = "insert into word_del (code, wordDel) values(@code, @wordDel)";
            commandWordDelAdd.Parameters.Add("@code", SqlDbType.Int);
            commandWordDelAdd.Parameters.Add("@wordDel", SqlDbType.Char, 30);
            //
            readerWord = commandWord.ExecuteReader();
            while (readerWord.Read())
            {
                word = readerWord.GetString(0).TrimEnd().ToLower();
                code = readerWord.GetInt32(1);
                for (i = 0; i < word.Length; i++)
                {
                    wordDel = word.Substring(0, i) + word.Substring(i + 1); // word без одной буквы
                    // Избегаем повторов
                    commandWordDel.Parameters["@code"].Value = code;
                    commandWordDel.Parameters["@wordDel"].Value = wordDel;
                    conWordDel.Open();
                    readerWordDel = commandWordDel.ExecuteReader();
                    found = readerWordDel.Read();
                    conWordDel.Close();
                    if (found)
                    {
                        k2++;
                        continue;
                    }
                    commandWordDelAdd.Parameters["@code"].Value = code;
                    commandWordDelAdd.Parameters["@wordDel"].Value = wordDel;
                    conWordDelAdd.Open();
                    commandWordDelAdd.ExecuteNonQuery();
                    conWordDelAdd.Close();
                    k++;
                }
            }
            conWord.Close();
            MessageBox.Show("Добавлено в word_del: " + k + '\n' + "Число повторов " + k2);
        }

Формирование word_del продолжается после добавления в all_words_dist новых, отсутствующих в all_words слов.
Выбор таких слов выполняется запросом, имеющим следующий текст:

select word, code from all_words_dist where code > @codeMax

После начального заполнения all_words_dist по all_words значение параметра @codeMax равно 4'257'382. Оно получается в результате выполнения следующего запроса:

select max(code) from all_words

Вычисление расстояния Левенштейна

Расстояние Левенштейна между строками s и t – это минимальное количество операций вставки символа, удаления символа и замены символа на другой, необходимых для превращения одной строки в другую [8].
Расстояние Левенштейна может быть использовано при правке текста при расчете цены замены слова на кандидат.
Расстояние Левенштейна возвращает следующая функция:

        // Расстояние Левенштейна между строками s и t
        // В результате вычислений в d[i,j] будет занесено расстояние Левенштейна
        // между первыми i символами строки s и первыми j символами строки t
        private int LevenshteinDistance(string s, string t)
        {
            int n = s.Length + 1, m = t.Length + 1, i, j, cost;
            int[,] d = new int[n, m];
            char s1;
            if (n == 0) return m - 1;
            if (m == 0) return n - 1;
            for (i = 0; i < n; i++) d[i, 0] = i;
            for (j = 0; j < m; j++) d[0, j] = j;
            for (i = 1; i < n; i++)
            {
                s1 = s[i - 1]; // Символ первой строки
                for (j = 1; j < m; j++)
                {
                    cost = (t[j - 1] == s1) ? 0 : 1;
                    d[i, j] = Math.Min(Math.Min(d[i - 1, j] + 1, d[i, j - 1] + 1), d[i - 1, j - 1] + cost);
                }
            }
            return d[n - 1, m - 1];
        }

Вычисление расстояния Дамерау-Левенштейна

Расстояние Дамерау-Левенштейна между строками s и t – это минимальное количество операций вставки символа, удаления символа, замены символа на другой и перестановки двух соседних символов, необходимых для превращения одной строки в другую [9].
Расстояние Дамерау-Левенштейна может быть использовано при правке текста при расчете цены замены слова на кандидат.
Расстояние Дамерау-Левенштейна возвращает следующая функция:

        private int DamerauLevenshteinDistance(string string1, string string2) // , int threshold)
        {
            // Тривиальный случай (1)
            if (string1.Equals(string2)) return 0;
            // Тривиальный случай (2)
            // x ?? y — возвращает x, если значение x отличается от null, или y - в противном случае
            if (String.IsNullOrEmpty(string1) || String.IsNullOrEmpty(string2)) return (string1 ?? "").Length + (string2 ?? "").Length;
            // Строка string2 (внутренний цикл) должна быть длиннее string1
            if (string1.Length > string2.Length)
            {
                var tmp = string1;
                string1 = string2;
                string2 = tmp;
            }
            // Тривиальный случай (3)
            if (string2.Contains(string1)) return string2.Length - string1.Length;
            //
            var length1 = string1.Length;
            var length2 = string2.Length;
            var d = new int[length1 + 1, length2 + 1];
            for (var i = 0; i <= d.GetUpperBound(0); i++) d[i, 0] = i;
            for (var i = 0; i <= d.GetUpperBound(1); i++) d[0, i] = i;
            for (var i = 1; i <= d.GetUpperBound(0); i++)
            {
                for (var j = 1; j <= d.GetUpperBound(1); j++)
                {
                    var cost = string1[i - 1] == string2[j - 1] ? 0 : 1;
                    var del = d[i - 1, j] + 1;
                    var ins = d[i, j - 1] + 1;
                    var sub = d[i - 1, j - 1] + cost;
                    d[i, j] = Math.Min(del, Math.Min(ins, sub));
                    if (i > 1 && j > 1 && string1[i - 1] == string2[j - 2] && string1[i - 2] == string2[j - 1])
                        d[i, j] = Math.Min(d[i, j], d[i - 2, j - 2] + cost);
                }
            }
            return d[d.GetUpperBound(0), d.GetUpperBound(1)];
        }

Программы разбора и правки текста

Обеспечивают работу приложения разбора и правки текста, пользовательский интерфейс которого показан на рис. 1.

Форма приложения

Рис. 1. Форма приложения разбора и правки текста

По результатам разбора текста пополняются следующие таблицы:

Таблица новых слов, а они так же добавляются и в all_words_dist, используется для пополнения таблицы слов-соседей. Оно выполняется после проверки новых слов: если в neighbors попало слово с ошибкой, то оно будет удалено и из neighbors, и из all_words_dist.
Проверка выполняется лицом, хорошо владеющим русским языком.
Правке текста выполняется в два этапа. На первом исправляются орфографические ошибки и ошибки, вызванные неправильным словообразованием. На втором – грамматические ошибки.
На первом этапе используется метод орфографической коррекции на основе алгоритма симметричного удаления [10].
На втором этапе решение о сохранении слова в тексте принимается на основе прецедентов, то есть случаев, имевших место ранее и служащих примером или оправданием для последующих случаев подобного рода [11].
В решаемой задаче прецедент считается найденным, если для проверяемого слова в таблице слов-соседей обнаружены такие же правые и / или левые соседи, что и в проверяемом тексте.
Приложение обращается к таблицам в all_words_dist и neighbors, пытаясь найти подходящую замену слову, не имеющему прецедентов.

Код приложения:

using System;
using System.Collections.Generic;
using System.Linq; // Where
using System.Text;
using System.Windows.Forms;
using System.IO; // StreamReader
using System.Data; // CommandType
using System.Data.SqlClient;
using System.Text.RegularExpressions; // Regex, RegexOptions

namespace WindowsFormsApplicationWordsWithoutLetter
{
 public partial class FormTextAnalysis : Form
 {
  int added, updated, newWords;
  string fl = ""; // Файл с разбираемым текстом
  string text; // Проверяемый текст,
  string textCandidates; // Проверяемое слово и кандидаты
  char[] punctuations = { ',', ';', '–', '!', '?', ':', '.', '«', '»', '"', '…', '(', ')', '[', ']', '„', '“', '<', '>', '—', '*', '&', '+' };
  string[] arrWords;
  string addr = "Data Source=HP-PC\\SQLEXPRESS;Initial Catalog=CrPr;Integrated Security=SSPI;";
  StreamReader sR;
  SqlDataReader readerWord, readerNeighbor, readerWordDel, readerWordCode, readerLeftContext, readerRightContext, readerPrecedents;
    //readerLeftPrecedents, readerRightPrecedents;
  SqlCommand cmdWord, cmdWordAdd, cmdNeighbor, cmdNeighborAdd, cmdNeighborUpdate, cmdNewWordAdd, cmdWordDel, cmdWordCode,
    cmdLeftContext, cmdRightContext, cmdPrecedents; // cmdLeftPrecedents, cmdRightPrecedents;
  SqlConnection conWord, conWordAdd, conNeighbor, conNeighborAdd, conNeighborUpdate, conNewWordAdd, conWordDel, conWordCode,
   conLeftContext, conRightContext, conPrecedents; //conLeftPrecedents, conRightPrecedents;
  int testNumber = 1; // Номер теста
  int minWordLen = 3; // Если длина слова меньше minWordLen, то оно не проверяется, а для замены выставляется с высоким показателем (равен 100)
  int maxCost = 4; // Максимально допустимая цена замены
  // Нижний порог соседств. Используется на втором этапе правки
  // Если число соседств предшествующего слова с текущим больше этого порога, то текущее слово считается правильным
  double replaceLowLevel = 10;
  List<Context> allCandidatesRight = new List<Context>();
  List<Context> allCandidatesLeft = new List<Context>();
  //
  public FormTextAnalysis()
  {
   InitializeComponent();
   //
   showText(1);
   //
   // Максимально допустимая цена замены
   maxCost = (int) numericUpDownCost.Value;
   //
   conWord = new SqlConnection(addr);
   cmdWord = new SqlCommand();
   cmdWord.CommandType = CommandType.Text;
   cmdWord.Connection = conWord;
   cmdWord.CommandText = "select code from all_words_dist with(index(word)) where word = @word";
   cmdWord.Parameters.Add("@word", SqlDbType.Char, 30);
   //
   conWordCode = new SqlConnection(addr);
   cmdWordCode = new SqlCommand();
   cmdWordCode.CommandType = CommandType.Text;
   cmdWordCode.Connection = conWordCode;
   cmdWordCode.CommandText = "select word from all_words_dist with(index(code)) where code = @code";
   cmdWordCode.Parameters.Add("@code", SqlDbType.Int);
   //
   conWordDel = new SqlConnection(addr);
   cmdWordDel = new SqlCommand();
   cmdWordDel.CommandType = CommandType.Text;
   cmdWordDel.Connection = conWordDel;
   // Добавляем distinct, поскольку слова типа осенний дают две записи с wordDel = осенний
   cmdWordDel.CommandText = "select distinct code from word_del with(index(wordDel)) where wordDel = @wordDel";
   cmdWordDel.Parameters.Add("@wordDel", SqlDbType.Char, 30);
   //
   conWordAdd = new SqlConnection(addr);
   cmdWordAdd = new SqlCommand();
   cmdWordAdd.CommandType = CommandType.Text;
   cmdWordAdd.Connection = conWordAdd;
   cmdWordAdd.CommandText = "insert into all_words_dist (word) values (@word)";
   cmdWordAdd.Parameters.Add("@word", SqlDbType.Char, 30);
   //
   conNewWordAdd = new SqlConnection(addr);
   cmdNewWordAdd = new SqlCommand();
   cmdNewWordAdd.CommandType = CommandType.Text;
   cmdNewWordAdd.Connection = conNewWordAdd;
   cmdNewWordAdd.CommandText = "insert into new_words (word, code) values (@word, @code)";
   cmdNewWordAdd.Parameters.Add("@word", SqlDbType.Char, 30);
   cmdNewWordAdd.Parameters.Add("@code", SqlDbType.Int);
   //
   conNeighbor = new SqlConnection(addr);
   cmdNeighbor = new SqlCommand();
   cmdNeighbor.CommandType = CommandType.Text;
   cmdNeighbor.Connection = conNeighbor;
   cmdNeighbor.CommandText = "select neighbourhood from neighbors with(index(code_code_neighbor))"
     + " where code = @code and code_neighbor = @code_neighbor";
   cmdNeighbor.Parameters.Add("@code", SqlDbType.Int);
   cmdNeighbor.Parameters.Add("@code_neighbor", SqlDbType.Int);
   //
   conNeighborAdd = new SqlConnection(addr);
   cmdNeighborAdd = new SqlCommand();
   cmdNeighborAdd.CommandType = CommandType.Text;
   cmdNeighborAdd.Connection = conNeighborAdd;
   cmdNeighborAdd.CommandText = "insert into neighbors (code, code_neighbor, neighbourhood)"
     + " values(@code, @code_neighbor, @neighbourhood)";
   cmdNeighborAdd.Parameters.Add("@code", SqlDbType.Int);
   cmdNeighborAdd.Parameters.Add("@code_neighbor", SqlDbType.Int);
   cmdNeighborAdd.Parameters.Add("@neighbourhood", SqlDbType.Int);
   //
   conNeighborUpdate = new SqlConnection(addr);
   cmdNeighborUpdate = new SqlCommand();
   cmdNeighborUpdate.CommandType = CommandType.Text;
   cmdNeighborUpdate.Connection = conNeighborUpdate;
   cmdNeighborUpdate.CommandText = "update neighbors set neighbourhood = @neighbourhood"
     + " where code = @code and code_neighbor = @code_neighbor";
   cmdNeighborUpdate.Parameters.Add("@neighbourhood", SqlDbType.Int);
   cmdNeighborUpdate.Parameters.Add("@code", SqlDbType.Int);
   cmdNeighborUpdate.Parameters.Add("@code_neighbor", SqlDbType.Int);
   //
   conLeftContext = new SqlConnection(addr);
   cmdLeftContext = new SqlCommand();
   cmdLeftContext.CommandType = CommandType.Text;
   cmdLeftContext.Connection = conLeftContext;
   cmdLeftContext.CommandText = "select code, neighbourhood from neighbors with(index(code_neighbor)) where code_neighbor = @code_neighbor";
   cmdLeftContext.Parameters.Add("@code_neighbor", SqlDbType.Int);
   //
   conRightContext = new SqlConnection(addr);
   cmdRightContext = new SqlCommand();
   cmdRightContext.CommandType = CommandType.Text;
   cmdRightContext.Connection = conRightContext;
   cmdRightContext.CommandText = "select code_neighbor, neighbourhood from neighbors with(index(code)) where code = @code";
   cmdRightContext.Parameters.Add("@code", SqlDbType.Int);
   //
   // Всего прецедентов слова с кодом @code
   conPrecedents = new SqlConnection(addr);
   cmdPrecedents = new SqlCommand();
   cmdPrecedents.CommandType = CommandType.Text;
   cmdPrecedents.Connection = conPrecedents;
   cmdPrecedents.CommandText = "select leftprecedents, rightprecedents from allprecedents with(index(code)) where code = @code";
   cmdPrecedents.Parameters.Add("@code", SqlDbType.Int);
   //
   //// Всего левых прецедентов (правых соседей) слова с кодом @code
   //conLeftPrecedents = new SqlConnection(addr);
   //cmdLeftPrecedents = new SqlCommand();
   //cmdLeftPrecedents.CommandType = CommandType.Text;
   //cmdLeftPrecedents.Connection = conLeftPrecedents;
   //cmdLeftPrecedents.CommandText = "select sum(neighbourhood) from neighbors where code = @code group by code";
   //cmdLeftPrecedents.Parameters.Add("@code", SqlDbType.Int);
   ////
   //// Всего правых прецедентов (левых соседей) слова с кодом @code
   //conRightPrecedents = new SqlConnection(addr);
   //cmdRightPrecedents = new SqlCommand();
   //cmdRightPrecedents.CommandType = CommandType.Text;
   //cmdRightPrecedents.Connection = conRightPrecedents;
   //cmdRightPrecedents.CommandText = "select sum(neighbourhood) from neighbors where code_neighbor = @code group by code_neighbor";
   //cmdRightPrecedents.Parameters.Add("@code", SqlDbType.Int);
  }
  private int fillPunct(string text, int tLen, List<int> punct)
  {
   int p, cnt;
   punct.Clear();
   cnt = 0;
   foreach (char m in punctuations)
   {
    p = text.IndexOf(m);
    if (p > -1)
    {
     punct.Add(p);
     cnt++;
    }
    else
     punct.Add(tLen);
   }
   return cnt;
  }
  private void selNeighborWordCode(int code, int code_neighbor)
  {
   bool fnd;
   int neighbourhood;
   cmdNeighbor.Parameters["@code"].Value = code;
   cmdNeighbor.Parameters["@code_neighbor"].Value = code_neighbor;
   conNeighbor.Open();
   readerNeighbor = cmdNeighbor.ExecuteReader();
   fnd = readerNeighbor.Read();
   neighbourhood = fnd ? readerNeighbor.GetInt32(0) + 1 : 1;
   conNeighbor.Close();
   if (fnd)
   {
    if (checkBoxUpdate.Checked)
    {
     cmdNeighborUpdate.Parameters["@neighbourhood"].Value = neighbourhood;
     cmdNeighborUpdate.Parameters["@code"].Value = code;
     cmdNeighborUpdate.Parameters["@code_neighbor"].Value = code_neighbor;
     conNeighborUpdate.Open();
     cmdNeighborUpdate.ExecuteNonQuery();
     conNeighborUpdate.Close();
     updated++;
    }
   }
   else
   {
    cmdNeighborAdd.Parameters["@code"].Value = code;
    cmdNeighborAdd.Parameters["@code_neighbor"].Value = code_neighbor;
    cmdNeighborAdd.Parameters["@neighbourhood"].Value = neighbourhood;
    conNeighborAdd.Open();
    cmdNeighborAdd.ExecuteNonQuery();
    conNeighborAdd.Close();
    added++;
   }
  }
  private int selWordCode(string word)
  {
   int code;
   cmdWord.Parameters["@word"].Value = word;
   conWord.Open();
   readerWord = cmdWord.ExecuteReader();
   code = readerWord.Read() ? readerWord.GetInt32(0) : -1;
   conWord.Close();
   if (code == -1)
   {
    // Добавляем новое слово в all_words_dist
    cmdWordAdd.Parameters["@word"].Value = word;
    conWordAdd.Open();
    cmdWordAdd.ExecuteNonQuery();
    conWordAdd.Close();
    //
    // Читаем code нового слова в all_words_dist
    conWord.Open();
    readerWord = cmdWord.ExecuteReader();
    readerWord.Read();
    code = readerWord.GetInt32(0);
    conWord.Close();
    //
    // Добавляем новое слово в new_words
    cmdNewWordAdd.Parameters["@code"].Value = code;
    cmdNewWordAdd.Parameters["@word"].Value = word;
    conNewWordAdd.Open();
    cmdNewWordAdd.ExecuteNonQuery();
    conNewWordAdd.Close();
    newWords++;
   }
   return code;
  }
  // Пополняет базу соседей
  private void addNeighbor(List<string> allWords)
  {
   int code, codeRight;
   foreach(string ws in allWords)
   {
    arrWords = ws.Split(' ').ToArray();
    for(int k = 0; k < arrWords.Count() - 1; k++)
    {
     code = selWordCode(arrWords[k]);
     codeRight = selWordCode(arrWords[k + 1]);
     if (code != codeRight) selNeighborWordCode(code, codeRight);
    }
   }
  }
  // Удаляем из words словоформы, длина которых меньше minWordLen, а также слова с цифрами
  private string shrinkWords(string words)
  {
   string ws, wrds = "";
   string[] arrWords = words.Replace('\t', ' ').Split(' ').ToArray();
   int k, i, wsLen;
   bool add;
   for(k = 0; k < arrWords.Count(); k++)
   {
    ws = arrWords[k].Trim();
    wsLen = ws.Length;
    if (wsLen < minWordLen) continue;
    if (ws[0] == '-')
    {
     ws = ws.Substring(1);
     wsLen--;
    }
    if (ws[wsLen - 1] == '-')
    {
     ws = ws.Substring(0, wsLen - 1);
     wsLen--;
    }
    add = true;
    for (i = 0; i < wsLen; i++)
    {
     if (Char.IsDigit(ws[i]))
     {
      add = false;
      break;
     }
    }
    if (add) wrds += ' ' + ws;
   }
   return wrds.TrimStart();
  }
  // Разбор текста
  private void buttonGo_Click(object sender, EventArgs e)
  {
   string text = "";
   string words = "";
   List<string> allWords = new List<string>();
   List<int> punct = new List<int>();
   int p, tLen, cnt;
   int k = 0;
   if (fl.Length == 0)
   {
    MessageBox.Show("Не выбран файл");
    return;
   }
   added = 0;
   updated = 0;
   newWords = 0;
   sR = new StreamReader(fl, Encoding.UTF8);
   while (!sR.EndOfStream)
   {
    text = sR.ReadLine().Trim();
    tLen = text.Length;
    if (tLen == 0) continue;
    k++;
    text = text.ToLower();
    text = text.Replace('ё', 'е'); // В словаре нет буквы ё
    cnt = fillPunct(text, tLen, punct);
    while (cnt > 0)
    {
     punct.Sort();
     p = punct[0];
     // Удаляем словоформы, длина которых меньше minWordLen
     words = shrinkWords(text.Substring(0, p).TrimEnd());
     //MessageBox.Show(words);
     if (words.Length > 0 && words.IndexOf(' ') > 0) allWords.Add(words);
     text = text.Substring(p + 1).TrimStart();
     cnt = fillPunct(text, tLen, punct);
    }
    if (text.Length > 0)
    {
     words = shrinkWords(text);
     //MessageBox.Show(words);
     if (words.Length > 0 && words.IndexOf(' ') > 0) allWords.Add(words);
    }
   }
   // Пополняем базу соседей
   addNeighbor(allWords);
   sR.Close();
   MessageBox.Show("Добавлено: " + added + ". Обновлено: " + updated + ". Новых: " + newWords);
  }
  // Поиск числа соседств
  private int findNeighborhood(string word, int candidateCode, bool left)
  {
   cmdWord.Parameters["@word"].Value = word;
   conWord.Open();
   readerWord = cmdWord.ExecuteReader();
   int code = readerWord.Read() ? readerWord.GetInt32(0) : -1;
   conWord.Close();
   if (code == -1 ) return 0;
   if (left)
   {
    cmdNeighbor.Parameters["@code"].Value = code;
    cmdNeighbor.Parameters["@code_neighbor"].Value = candidateCode;
   }
   else
   {
    cmdNeighbor.Parameters["@code"].Value = candidateCode;
    cmdNeighbor.Parameters["@code_neighbor"].Value = code;
   }
   conNeighbor.Open();
   readerNeighbor = cmdNeighbor.ExecuteReader();
   bool fnd = readerNeighbor.Read();
   int neighbourhood = fnd ? readerNeighbor.GetInt32(0) : -1;
   conNeighbor.Close();
   return neighbourhood;
  }
  private void addToCandidates(string wordDel, bool isUpper, List<Candidate> allCandidates)
  {
   int candidateCode;
   string candidate;
   cmdWordDel.Parameters["@wordDel"].Value = wordDel;
   conWordDel.Open();
   readerWordDel = cmdWordDel.ExecuteReader();
   while (readerWordDel.Read())
   {
    candidateCode = readerWordDel.GetInt32(0);
    if (candidateCode > 0)
    {
     // Поиск в all_words_dist по code
     cmdWordCode.Parameters["@code"].Value = candidateCode;
     conWordCode.Open();
     readerWordCode = cmdWordCode.ExecuteReader();
     if (readerWordCode.Read())
     {
      candidate = readerWordCode.GetString(0).Trim();
      candidate = isUpper ? candidate.ToUpper().Substring(0, 1) + candidate.Substring(1) : candidate;
      allCandidates.Add(new Candidate() { CandidateName = candidate, CandidateCode = candidateCode });
     }
     conWordCode.Close();
    }
   }
   conWordDel.Close();
  }
  private void addToCandidatesFromAll_words_dist(string word, bool isUpper, List<Candidate> allCandidates, bool space)
  {
   int candidateCode;
   string candidate;
   bool no = false;
   // Если space = истина, то слово с пробелом
   if (space && word.Substring(0, 2) == "не" && Regex.Matches(word.Substring(word.Length - 1), @"[цкнгшщзхфвпрлджчсмтб]", RegexOptions.IgnoreCase).Count == 1)
   {
    //MessageBox.Show("" + Regex.Matches(word.Substring(word.Length - 1), @"[цкнгшщзхфвпрлджчсмтб]", RegexOptions.IgnoreCase).Count);
    no = true;
    word = word.Substring(3);
   }
   // Ищем прежде укороченное слово в all_words_dist
   cmdWord.Parameters["@word"].Value = word;
   conWord.Open();
   readerWord = cmdWord.ExecuteReader();
   if (readerWord.Read())
   {
    candidateCode = readerWord.GetInt32(0);
    if (no) word = "не " + word;
    //MessageBox.Show("" + candidateCode);
    candidate = isUpper ? word.ToUpper().Substring(0, 1) + word.Substring(1) : word;
    allCandidates.Add(new Candidate() { CandidateName = candidate, CandidateCode = candidateCode });
   }
   conWord.Close();
  }
  private int findPrecedentsCount(int candidateCode)
  {
   int leftPrecedents = 0, rightPrecedents = 0;
   //
   //cmdLeftPrecedents.Parameters["@code"].Value = candidateCode;
   //conLeftPrecedents.Open();
   //readerLeftPrecedents = cmdLeftPrecedents.ExecuteReader();
   //if (readerLeftPrecedents.Read()) leftPrecedentsCount = readerLeftPrecedents.GetInt32(0);
   //conLeftPrecedents.Close();
   //
   //cmdRightPrecedents.Parameters["@code"].Value = candidateCode;
   //conRightPrecedents.Open();
   //readerRightPrecedents = cmdRightPrecedents.ExecuteReader();
   //if (readerRightPrecedents.Read()) rightPrecedentsCount = readerRightPrecedents.GetInt32(0);
   //conRightPrecedents.Close();
   //
   cmdPrecedents.Parameters["@code"].Value = candidateCode;
   conPrecedents.Open();
   readerPrecedents = cmdPrecedents.ExecuteReader();
   if (readerPrecedents.Read())
   {
    leftPrecedents = readerPrecedents.GetInt16(0);
    rightPrecedents = readerPrecedents.GetInt16(1);
   }
   conPrecedents.Close();
   return leftPrecedents + rightPrecedents;
  }
  private int vowelLetters(string word) // Возвращает число гласных в слове
  {
   return Regex.Matches(word, @"[уеыаоэяиёю]", RegexOptions.IgnoreCase).Count;
  }
  private int addSymb(string symb, string word, bool isUpper, List<Candidate> allCandidates)
  {
   int cnt2 = 0;
   // Добавляем symb после i-го символа word
   for (int i = 1; i < word.Length - 1; i++)
   {
    word = word.Insert(i, symb);
    //MessageBox.Show(word);
    addToCandidatesFromAll_words_dist(word, isUpper, allCandidates, symb == " ");
    cnt2 = allCandidates.Count;
    if (cnt2 > 0) break;
    word = word.Remove(i, 1);
   }
   return cnt2;
  }
  private string checkWords_1(string words) // Первый проход правки текста
  {
   int code0, wordIndex, i, cnt, cnt2 = 0, levDist, candidateCode, vowLetInWord, precedentsCount;
   //int leftNeigh = 0, rightNeigh = 0;
   string word0, word, wordDel, candidate;
   List<Candidate> allCandidates = new List<Candidate>();
   bool isUpper;
   //
   MessageBox.Show("Этап 1: " + words);
   arrWords = words.Split(' ').ToArray();
   cnt = arrWords.Count();
   words = "";
   for (wordIndex = 0; wordIndex < cnt; wordIndex++)
   {
    allCandidates.Clear();
    word0 = arrWords[wordIndex];
    word = word0.ToLower();
    vowLetInWord = vowelLetters(word); // Число гласных в слове
    isUpper = word0[0] != word[0];
    //
    // Поиск проверяемого слова в all_words_dist. Если найдено, то переход к следующему слову
    cmdWord.Parameters["@word"].Value = word;
    conWord.Open();
    readerWord = cmdWord.ExecuteReader();
    code0 = readerWord.Read() ? readerWord.GetInt32(0) : -1;
    conWord.Close();
    if (code0 == -1) // Слова нет в all_words_dist
    {
     // Случай слитного написания двух слов
     cnt2 = addSymb(" ", word, isUpper, allCandidates);
     // Случай пропуска дефиса
     if (cnt2 == 0) cnt2 = addSymb("-", word, isUpper, allCandidates);
     if (cnt2 == 0)
     {
      // Ищем прежде исходное слово в word_del
      addToCandidates(word, isUpper, allCandidates);
      // Поиск в word_del укороченных слов
      for (i = 0; i < word.Length; i++)
      {
       wordDel = word.Substring(0, i) + word.Substring(i + 1); // word без одной буквы
       addToCandidatesFromAll_words_dist(wordDel, isUpper, allCandidates, false);
       addToCandidates(wordDel, isUpper, allCandidates);
      }
      cnt2 = allCandidates.Count;
     }
     if (cnt2 > 0) // Слова нет all_words_dist, но найдены кандидаты в word_del
     {
      if (cnt2 == 1)
       word0 = allCandidates[0].CandidateName;
      else
      {
       for (i = 0; i < cnt2; i++)
       {
        candidate = allCandidates[i].CandidateName;
        candidateCode = allCandidates[i].CandidateCode;
        // Расстояние Левенштейна между кандидатом и исправляемым словом
        //levDist = LevenshteinDistance(candidate, word);
        levDist = DamerauLevenshteinDistance(candidate, word);
        // Число соседств с предшествующим словом
        //leftNeigh = wordIndex > 0 ? findNeighborhood(arrWords[wordIndex - 1], candidateCode, true) : 0;
        //// Число соседств с последующим словом
        //if (leftNeigh == -1)
        // rightNeigh = 0;
        //else
        // rightNeigh = wordIndex < cnt - 1 ? findNeighborhood(arrWords[wordIndex + 1], candidateCode, false) : 0;
        //if (rightNeigh == -1) leftNeigh = 0;
        //allCandidates[i].CandidateFactor = leftNeigh + rightNeigh - levDist;
        precedentsCount = -findPrecedentsCount(candidateCode);
        allCandidates[i].CandidateFactor = levDist + (vowLetInWord == vowelLetters(candidate) ? 0 : 1) + (precedentsCount == 0 ? 1 : 0);
        allCandidates[i].CandidatePrecedentsCount = precedentsCount;
       }
       //
       //Console.WriteLine("\nДо сортировки:");
       //foreach (Candidate cand in allCandidates) Console.WriteLine(cand.CandidateName + " - " + cand.CandidateFactor + " - " + cand.CandidatePrecedentsCount);
       //
       //allCandidates.Sort(); // Сортировка по убыванию показателя CandidateFactor
       //word0 = allCandidates[0].CandidateName;
       // Вариант сортировки по двум показателям
       //var result = users.OrderBy(u => u.Name).ThenBy(u => u.Age).ThenBy(u => u.Name.Length); // ThenByDescending()
       //var result = from user in allCandidates orderby user.CandidateFactor, user.CandidatePrecedentsCount select user;
       // result.ElementAt(0).CandidateFactor
       //
       fillInTextBoxCandidates(word, allCandidates, false);
       word0 = allCandidates[0].CandidateName;
       word0 = word0.Substring(word0.IndexOf(" ") + 1);
      }
     }
    }
    arrWords[wordIndex] = word0.ToLower();
    words += word0 + (wordIndex < cnt - 1 ? " " : "");
   }
   return words;
  }
  // Возвращает максимально допустимую цену замены maxCost
  // Для предсказания maxCost можно использовать нейронную сеть, обученную для решения этой задачи,
  // или иной меттод машинного обучения
  private int findMaxCost(string word)
  {
   int maxCost = Math.Max((int)numericUpDownCost.Minimum, word.Length - 2);
   maxCost = Math.Min((int)numericUpDownCost.Maximum, maxCost);
   numericUpDownCost.Value = maxCost;
   return maxCost;
  }
  private double findReplaceLowLevel(int code0)
  {
   return 10;
  }
  // Оставляем слово, если оно есть
  // - в обоих контекстах
  // или
  // - только в правом контексте предшествующего слова и число соседств текущего слова
  // с предшествующим словом больше нижнего порога replaceLowLevel
  private bool wordShouldBeKept(int code0Left, int code0)
  {
   if (allCandidatesLeft.Exists(x => x.CandidateCode == code0) && allCandidatesRight.Exists(x => x.CandidateCode == code0))
    return true;
   else
   {
    int neighCount = 0; // Число соседств текущего слова с предшествующим словом
    if (allCandidatesRight.Exists(x => x.CandidateCode == code0))
    {
     Context contR0 = allCandidatesRight.Find(x => x.CandidateCode == code0);
     neighCount = contR0.CandidateFactor;
    }
    return neighCount >= replaceLowLevel;
   }
  }
  private string checkWords_2(string words) // Второй проход правки текста
  {
   int wordIndex, wordIndex2, cnt, cnt2, cnt2_1, code0, code0Left = 0, code0Right = 0; //, vowLetInWord;
   string words2, word0, word, wordLeft = "", wordRight = "";
   string[] arrWords2;
   bool isUpper, replaceWord0;
   List<Candidate> allCandidates = new List<Candidate>();
   //
   List<Candidate> allCandidatesR0 = new List<Candidate>(); // Для правого контекста текущего слова
   List<Context> allCandidatesRight0 = new List<Context>();
   //
   words2 = shrinkWords(words); // Удаляем слова, длина которых менее minWordLen (minWordLen = 3)
   MessageBox.Show("Этап 2: " + words2);
   arrWords2 = words2.Split(' ').ToArray();
   cnt2 = arrWords2.Count();
   if (cnt2 < 2) return words;
   arrWords = words.Split(' ').ToArray(); // Для восстановления исходного текста
   cnt = arrWords.Count();
   cnt2_1 = cnt2 - 1;
   wordIndex2 = -1;
   words = ""; // Проверенный текст
   for (wordIndex = 0; wordIndex < cnt; wordIndex++)
   {
    word0 = arrWords[wordIndex];
    if (word0.Length >= minWordLen)
    {
     wordIndex2++;
     word0 = arrWords2[wordIndex2];
     word = word0.ToLower(); // Текущее слово в нижнем регистре
     //vowLetInWord = vowelLetters(word);
     isUpper = word0[0] != word[0];
     replaceWord0 = false; // Флаг замены текущего слова
     allCandidates.Clear();
     allCandidatesRight.Clear();
     allCandidatesLeft.Clear();
     //
     // Поиск в all_words_dist
     // select code from all_words_dist with(index(word)) where word = @word
     cmdWord.Parameters["@word"].Value = word;
     conWord.Open();
     readerWord = cmdWord.ExecuteReader();
     code0 = readerWord.Read() ? readerWord.GetInt32(0) : -1; // Код текущего слова в all_words_dist
     conWord.Close();
     //
     //maxCost = findMaxCost(word);
     maxCost = 2; // Для второго этапа
     replaceLowLevel = findReplaceLowLevel(code0);
     //
     // Правый контекст предшествующего слова wordLeft = arrWords2[wordIndex2 - 1]
     if (wordIndex2 > 0)
     {
      wordLeft = arrWords2[wordIndex2 - 1];
      code0Left = fillInAllCandidates(allCandidatesRight, wordLeft, true);
     }
     if (wordIndex2 < cnt2_1)
     {
      wordRight = arrWords2[wordIndex2 + 1];
      // Левый контекст слова следующего слова wordRight = arrWords2[wordIndex2 + 1]
      code0Right = fillInAllCandidates(allCandidatesLeft, wordRight, false);
     }
     //
     //Console.WriteLine("\nСлово найдено в all_words_dist. Проверяемое слово: " + word0);
     //if (wordIndex2 > 0) Console.WriteLine("\nПредшествующее слово : " + arrWords2[wordIndex2 - 1]);
     //if (wordIndex2 < cnt2_1 - 1) Console.WriteLine("\nПоследующее слово : " + arrWords2[wordIndex2 + 1]);
     //Console.WriteLine("\nРазмеры правого и левого контекстов : " + allCandidatesRight.Count + " и " + allCandidatesLeft.Count);
     //
     if (allCandidatesRight.Count > 0 && allCandidatesLeft.Count > 0) // Есть правый и левый контексты
     {
      //Console.WriteLine("\nПроверяемое слово (есть оба контекста): " + word0);
      //Console.WriteLine("\nПравый контекст предшествующего слова: " + arrWords2[wordIndex2 - 1]);
      //foreach (Context contR in allCandidatesRight) Console.WriteLine(findCandidateName(contR.CandidateCode) + " - " + contR.CandidateFactor);
      //Console.WriteLine("\nЛевый контекст последующего слова: " + arrWords2[wordIndex2 + 1]);
      //foreach (Context contL in allCandidatesLeft) Console.WriteLine(findCandidateName(contL.CandidateCode) + " - " + contL.CandidateFactor);
      //
      // Оставляем слово, если оно есть
      // - в обоих контекстах
      // или
      // - только в правом контексте предшествующего слова и число соседств текущего слова
      // с предшествующим словом больше нижнего порога replaceLowLevel
      if (!wordShouldBeKept(code0Left, code0))
      {
       // Добавляем в список кандидатов только те слова, которые есть в обоих контекстах
       foreach (Context contR in allCandidatesRight)
       {
        int codeR = contR.CandidateCode;
        //Console.WriteLine("\nПроверяется кандидат: " + findCandidateName(codeR));
        if (allCandidatesLeft.Exists(x => x.CandidateCode == codeR))
        {
         Context contL = allCandidatesLeft.Find(x => x.CandidateCode == codeR);
         // select code_neighbor, neighbourhood from neighbors with(index(code)) where code = @code, поэтому
         // contL.CandidateCode = code_neighbor
         // contL.CandidateFactor = neighbourhood - число соседств в таблице соседей
         //Console.WriteLine("\nДля слова " + word0 + " добавлен кандидат " + findCandidateName(codeR));
         allCandidates.Add(new Candidate()
         {
          CandidateCode = codeR,
          CandidateFactor = findCandidateFactor(word, contR.CandidateCode, contR.CandidateFactor + contL.CandidateFactor, true),
          CandidatePrecedentsCount = -findPrecedentsCount(codeR)
          // CandidateFactor - расстояние Дамерау-Левенштейна между текущим словом word и кандидатом на замещение,
          // который ищется по коду contR.CandidateCode: select word from all_words_dist with(index(code)) where code = @code
         });
        }
       }
       //MessageBox.Show("" + allCandidates.Count);
       if (allCandidates.Count > 0)
       {
        // Заменяем слово, если оно есть в правом контексте предшествующего слова, а цена замены меньше допустимой величины
        //if (allCandidatesRight.Exists(x => x.CandidateCode == code0))
        //{
        // Ищем слово в его объединенном контексте
        fillInTextBoxCandidates(word, allCandidates, true);
        replaceWord0 = allCandidates[0].CandidateFactor <= maxCost;
        //
        //Console.WriteLine("\nЗаменяем слово " + word0 + " на слово с кодом " + allCandidates[0].CandidateCode);
        //Console.WriteLine("\nПоказатель: " + allCandidates[0].CandidateFactor + Environment.NewLine);
        //}
        //Console.WriteLine("\nОбъединенный контекст слов: " + wordLeft + " и " + wordRight);
        //foreach (Candidate cand in allCandidates) Console.WriteLine(cand.CandidateCode + " - " + cand.CandidateFactor);
       }
      }
     }
     else if (allCandidatesRight.Count > 0) // Ищем слово в правом контексте предшествующего слова
     {
      //Console.WriteLine("\nИщем слово " + word0 + " в правом контексте предшествующего слова: " + arrWords2[wordIndex2 - 1]);
      // Оставляем слово, если оно есть в правом контексте предшествующего слова
      // Иначе формируем список кандидатов из пересечения левых и правых прецедентов (правых и левых контекстов)
      if (!allCandidatesRight.Exists(x => x.CandidateCode == code0))
      {
       foreach (Context contR in allCandidatesRight)
       {
        int codeR = contR.CandidateCode;
        allCandidates.Add(new Candidate()
        {
         CandidateCode = codeR,
         CandidateFactor = findCandidateFactor(word, codeR, contR.CandidateFactor, true),
         CandidatePrecedentsCount = -findPrecedentsCount(codeR)
        });
        //
        //MessageBox.Show(word + " : " + (replaceWord0 ? "Меняем" : "Оставляем"));
        //
        //Console.WriteLine("\nПраверяется слово: " + word);
        //Console.WriteLine("\nПравый контекст слова: " + wordLeft);
        //foreach (Candidate cand in allCandidates)
        //{
        // // Находим слово по его коду
        // cmdWordCode.Parameters["@code"].Value = cand.CandidateCode;
        // conWordCode.Open();
        // readerWordCode = cmdWordCode.ExecuteReader();
        // readerWordCode.Read();
        // cand.CandidateName = readerWordCode.GetString(0).Trim();
        // conWordCode.Close();
        //}
        //foreach (Candidate cand in allCandidates) Console.WriteLine(cand.CandidateName + " - " + cand.CandidateFactor);
        //
       }
       if (allCandidates.Count > 0)
       {
        // Оставляем word0 (word), если его замена "дороже" замены текущего слова
        fillInTextBoxCandidates(word, allCandidates, true);
        replaceWord0 = allCandidates[0].CandidateFactor <= maxCost;
       }
      }
      //else
      // Console.WriteLine("\nПоиск в правом контексте. Оставили слово " + word0);
     }
     else if (allCandidatesLeft.Count > 0) // Ищем слово в левом контексте последующего слова
     {
      // Оставляем слово, если оно есть в левом контексте
      if (!allCandidatesLeft.Exists(x => x.CandidateCode == code0))
      {
       //Console.WriteLine("\nИщем замену слову " + word0 + " в левом контексте последующего слова: " + arrWords2[wordIndex2 + 1]);
       // Ищем замену текущему слову в левом контексте последующего слова либо оставляем это слово без изменения
       foreach (Context contL in allCandidatesLeft)
        allCandidates.Add(new Candidate()
        {
         CandidateCode = contL.CandidateCode,
         CandidateFactor = findCandidateFactor(word, contL.CandidateCode, contL.CandidateFactor, true),
         CandidatePrecedentsCount = -findPrecedentsCount(contL.CandidateCode)
        });
       if (wordIndex2 < cnt2_1) // Находим правый контекст текущего слова
       {
        allCandidatesRight0.Clear();
        fillInAllCandidates(allCandidatesRight0, word, true); // Правый контекст текущего слова word0 = arrWords2[wordIndex2]
        // Проверяем, есть ли слово wordRight в правом контексте текущего слова word0
        if (!allCandidatesRight0.Exists(x => x.CandidateCode == code0Right)) // Слова wordRight нет в правом контексте текущего слова word0. Ищем ему замену
        {
         //allCandidatesR0.Clear();
         //foreach (Context contR0 in allCandidatesRight0) // allCandidatesRight0 - правый контекст текущего слова
         // allCandidatesR0.Add(new Candidate()
         // {
         //  CandidateCode = contR0.CandidateCode,
         //  CandidateFactor = findCandidateFactor(wordRight, contR0.CandidateCode, contR0.CandidateFactor, true)
         // });
         //if (allCandidates.Count > 0 && allCandidatesR0.Count > 0)
         //{
         // // Оставляем word0 (word), если его замена "дороже" замены текущего слова
         // allCandidates.Sort(); // Сортировка по возрастанию показателя CandidateFactor
         // allCandidatesR0.Sort();
         // replaceWord0 = allCandidatesR0[0].CandidateFactor > allCandidates[0].CandidateFactor;
         // //Console.WriteLine("\nСлово " + word + " показатель: " + allCandidatesR0[0].CandidateFactor);
         // //Console.WriteLine("\nСлово " + arrWords2[wordIndex + 1] + " показатель: " + allCandidates[0].CandidateFactor);
         //}
         if (allCandidates.Count > 0)
         {
          // Оставляем word0 (word), если его замена "дороже" замены текущего слова
          fillInTextBoxCandidates(word, allCandidates, true);
          replaceWord0 = allCandidates[0].CandidateFactor <= maxCost;
          //Console.WriteLine("\nСлово " + arrWords2[wordIndex + 1] + " показатель: " + allCandidates[0].CandidateFactor);
         }
        }
       }
      }
     }
     //else
     // Console.WriteLine("\nПоиск в левом контексте. Оставили слово " + word0);
     if (replaceWord0)
     {
      word0 = allCandidates[0].CandidateName;
      word0 = isUpper ? word0.ToUpper().Substring(0, 1) + word0.Substring(1) : word0;
     }
     arrWords2[wordIndex2] = word0.ToLower();
    }
    words += word0 + (wordIndex < cnt - 1 ? " " : "");
   }
   return words;
  }
  private void fillInTextBoxCandidates(string word, List<Candidate> allCandidates, bool findName)
  {
   int k = 0;
   List<Candidate> tmp = new List<Candidate>();
   // Сортировка по цене замены и числу прецедентов
   var result = from user in allCandidates orderby user.CandidateFactor, user.CandidatePrecedentsCount select user;
   foreach (Candidate cand in result) tmp.Add(cand);
   allCandidates.Clear();
   foreach (Candidate cand in tmp) allCandidates.Add(cand);
   labelWord.Text = word;
   // Выводим первые 10 кандидатов
   textCandidates = "";
   foreach (Candidate cand in allCandidates)
   {
    string candName = findCandidateName(cand, findName);
    allCandidates[k].CandidateName = candName;
    k++;
    if (k > 10) break;
    textCandidates += candName + "/" + cand.CandidateFactor + "/" + (-cand.CandidatePrecedentsCount) + "\r\n";
   }
   textBoxCandidates.Text = textCandidates;
   MessageBox.Show("OK");
  }
  private string findCandidateName(Candidate cand, bool findName)
  {
   string candidate = "";
   if (findName)
   {
    cmdWordCode.Parameters["@code"].Value = cand.CandidateCode;
    conWordCode.Open();
    readerWordCode = cmdWordCode.ExecuteReader();
    if (readerWordCode.Read()) candidate = readerWordCode.GetString(0).Trim();
    conWordCode.Close();
   }
   else
    candidate = cand.CandidateName;
   return candidate;
  }
  private string findCandidateName(int code)
  {
   string candidate = "";
   cmdWordCode.Parameters["@code"].Value = code;
   conWordCode.Open();
   readerWordCode = cmdWordCode.ExecuteReader();
   if (readerWordCode.Read()) candidate = readerWordCode.GetString(0).Trim();
   conWordCode.Close();
   return candidate;
  }
  private int findCandidateFactor(string word, int code, int factor, bool Levenshtein)
  {
   if (Levenshtein)
   {
    // select word from all_words_dist with(index(code)) where code = @code
    cmdWordCode.Parameters["@code"].Value = code;
    conWordCode.Open();
    readerWordCode = cmdWordCode.ExecuteReader();
    readerWordCode.Read();
    string candidate = readerWordCode.GetString(0).Trim();
    conWordCode.Close();
    //int candidateFactor = candidate.Length < minWordLen ? 100 : LevenshteinDistance(candidate, word);
    int candidateFactor = candidate.Length < minWordLen ? 100 : DamerauLevenshteinDistance(candidate, word);
    //
    //Console.WriteLine("\nСлово " + word);
    //Console.WriteLine("\nКандидат " + candidate);
    //Console.WriteLine("\nПоказатель " + candidateFactor);
    return candidateFactor;
   }
   else
    return factor;
  }
  private int fillInAllCandidates(List<Context> allCandidatesRL, string word, bool right)
  {
   if (word.Length < minWordLen) return -1;
   cmdWord.Parameters["@word"].Value = word.ToLower();
   conWord.Open();
   readerWord = cmdWord.ExecuteReader();
   int code = readerWord.Read() ? readerWord.GetInt32(0) : -1;
   conWord.Close();
   if (code == -1) return code;
   if (right)
   { // Правый контекст предшествующего слова
    // select code_neighbor, neighbourhood from neighbors with(index(code)) where code = @code
    cmdRightContext.Parameters["@code"].Value = code;
    conRightContext.Open();
    readerRightContext = cmdRightContext.ExecuteReader();
    while (readerRightContext.Read())
     allCandidatesRL.Add(new Context() { CandidateCode = readerRightContext.GetInt32(0), CandidateFactor = readerRightContext.GetInt32(1) });
    conRightContext.Close();
   }
   else
   {
    // select code, neighbourhood from neighbors with(index(code_neighbor)) where code_neighbor = @code_neighbor
    cmdLeftContext.Parameters["@code_neighbor"].Value = code;
    conLeftContext.Open();
    readerLeftContext = cmdLeftContext.ExecuteReader();
    while (readerLeftContext.Read())
     allCandidatesRL.Add(new Context() { CandidateCode = readerLeftContext.GetInt32(0), CandidateFactor = readerLeftContext.GetInt32(1) });
    conLeftContext.Close();
   }
   return code;
  }
  // Правка текста
  private void buttonCheck_Click(object sender, EventArgs e)
  {
   int p, cnt;
   string line, words = "", textChecked = "", c;
   List<int> punct = new List<int>();
   labelWord.Text = "";
   textBoxCandidates.Text = "";
   if (text.Trim().Length == 0)
   {
    if (fl.Length == 0)
     MessageBox.Show("Не выбран файл");
    else // Заполняем текстовое из файла
    {
     sR = new StreamReader(fl, Encoding.UTF8);
     while (!sR.EndOfStream) text += (sR.ReadLine() + Environment.NewLine);
     sR.Close();
    }
   }
   if (text.Trim().Length == 0)
   {
    MessageBox.Show("Пусто");
    return;
   }
   //
   // Первый проход
   text = text.Trim();
   text = text.Replace('ё', 'е'); // В словаре нет буквы ё
   while (text.Length > 0)
   {
    p = text.IndexOf(Environment.NewLine);
    if (p == 0)
    {
     text = text.Substring(p + 1).Trim();
     textChecked += Environment.NewLine;
     continue;
    }
    else
    {
     if (p == -1)
     {
      line = text;
      text = "";
     }
     else
     {
      line = text.Substring(0, p).Trim();
      text = text.Substring(p + 1).Trim();
     }
    }
    //MessageBox.Show(line);
    // punct - список знаков препинаний в строке line
    cnt = fillPunct(line, line.Length, punct);
    while (cnt > 0)
    {
     punct.Sort();
     p = punct[0];
     words = line.Substring(0, p).Trim(); // Подстрока до первого знака препинания
     //if (words.Length > 0 && words.IndexOf(' ') > 0)
     if (words.Length > 0)
     {
      textChecked += checkWords_1(words);
     }
     else
      textChecked += words;
     c = line.Substring(p, 1);
     textChecked += (p > 0 && (c == "–" || c == "—") ? " " : "") + c + " ";
     line = line.Substring(p + 1);
     cnt = fillPunct(line, line.Length, punct);
    }
    if (line.Length > 0) textChecked += checkWords_1(line);
    textChecked += Environment.NewLine;
   }
   //
   textBoxAfterCheck.Text = textChecked;
   if (checkBoxOneStep.Checked) return;
   //
   // Второй проход
   text = textChecked;
   textChecked = "";
   while (text.Length > 0)
   {
    p = text.IndexOf(Environment.NewLine);
    if (p == 0)
    {
     text = text.Substring(p + 1).Trim();
     textChecked += Environment.NewLine;
     continue;
    }
    else
    {
     if (p == -1)
     {
      line = text;
      text = "";
     }
     else
     {
      line = text.Substring(0, p).Trim();
      text = text.Substring(p + 1).Trim();
     }
    }
    //MessageBox.Show(text);
    // punct - список знаков препинаний в строке line
    cnt = fillPunct(line, line.Length, punct);
    while (cnt > 0)
    {
     punct.Sort();
     p = punct[0];
     words = line.Substring(0, p).Trim(); // Подстрока до первого знака препинания
     if (words.Length > 0 && words.IndexOf(' ') > 0)
      textChecked += checkWords_2(words);
     else
      textChecked += words;
     c = line.Substring(p, 1);
     textChecked += (p > 0 && (c == "–" || c == "—") ? " " : "") + c + " ";
     line = line.Substring(p + 1);
     cnt = fillPunct(line, line.Length, punct);
    }
    if (line.Length > 0) textChecked += checkWords_2(line);
    textChecked += Environment.NewLine;
   }
   //
   textBoxAfterCheck2.Text = textChecked;
   //MessageBox.Show("Готово");
  }
  private void buttonClear_Click(object sender, EventArgs e)
  {
   labelWord.Text = "";
   textBoxCheck.Text = "";
   textBoxAfterCheck.Text = "";
   textBoxAfterCheck2.Text = "";
   textBoxCandidates.Text = "";
  }
  private int DamerauLevenshteinDistance(string string1, string string2) // , int threshold)
  {
   // Тривиальный случай (1)
   if (string1.Equals(string2)) return 0;
   // Тривиальный случай (2)
   // x ?? y — возвращает x, если значение x отличается от null, или y - в противном случае
   if (String.IsNullOrEmpty(string1) || String.IsNullOrEmpty(string2)) return (string1 ?? "").Length + (string2 ?? "").Length;
   // Строка string2 (внутренний цикл) должна быть длиннее string1
   if (string1.Length > string2.Length)
   {
    var tmp = string1;
    string1 = string2;
    string2 = tmp;
   }
   // Тривиальный случай (3)
   if (string2.Contains(string1)) return string2.Length - string1.Length;
   //
   var length1 = string1.Length;
   var length2 = string2.Length;
   var d = new int[length1 + 1, length2 + 1];
   for (var i = 0; i <= d.GetUpperBound(0); i++) d[i, 0] = i;
   for (var i = 0; i <= d.GetUpperBound(1); i++) d[0, i] = i;
   for (var i = 1; i <= d.GetUpperBound(0); i++)
   {
    for (var j = 1; j <= d.GetUpperBound(1); j++)
    {
     var cost = string1[i - 1] == string2[j - 1] ? 0 : 1;
     var del = d[i - 1, j] + 1;
     var ins = d[i, j - 1] + 1;
     var sub = d[i - 1, j - 1] + cost;
     d[i, j] = Math.Min(del, Math.Min(ins, sub));
     if (i > 1 && j > 1 && string1[i - 1] == string2[j - 2] && string1[i - 2] == string2[j - 1])
      d[i, j] = Math.Min(d[i, j], d[i - 2, j - 2] + cost);
    }
   }
   return d[d.GetUpperBound(0), d.GetUpperBound(1)];
  }
  // В результате вычислений в d[i,j] будет занесено расстояние Левенштейна
  // между первыми i символами строки s и первыми j символами строки t
  private int LevenshteinDistance(string s, string t)
  {
   int levDist;
   // Обе строки в нижнем регистре
   int n = s.Length + 1, m = t.Length + 1, i, j, cost;
   int[,] d = new int[n, m];
   char s1;
   if (n == 0) return m - 1;
   if (m == 0) return n - 1;
   for (i = 0; i < n; i++) d[i, 0] = i;
   for (j = 0; j < m; j++) d[0, j] = j;
   for (i = 1; i < n; i++)
   {
    s1 = s[i - 1]; // Символ первой строки
    for (j = 1; j < m; j++)
    {
     cost = (t[j - 1] == s1) ? 0 : 1;
     d[i, j] = Math.Min(Math.Min(d[i - 1, j] + 1, d[i, j - 1] + 1), d[i - 1, j - 1] + cost);
    }
   }
   levDist = d[n - 1, m - 1];
   return levDist;
  }
  private void buttonFile_Click(object sender, EventArgs e)
  {
   OpenFileDialog OPF = new OpenFileDialog();
   OPF.Filter = "txt-файлы (*.txt)|*.txt";
   DialogResult dlg = OPF.ShowDialog(); // Выбираем txt-файл
   if (dlg == DialogResult.OK)
   {
    fl = OPF.FileName.Trim();
    labelFile.Text = "Выбран файл: " + fl;
   }
  }
  private void buttonClose_Click(object sender, EventArgs e)
  {
   Close();
  }
  private void numericUpDownCost_ValueChanged(object sender, EventArgs e)
  {
   maxCost = (int)numericUpDownCost.Value;
  }
  private void showText(int testNumber)
  {
   switch (testNumber)
   {
    case 1: // Замена буквы
     text = "Внизапно пашел снег.";
     break;
    case 2:
     text = "Прелетели грачи.";
     break;
    case 3:
     text = "Как зЯленое пламя, вспыхнулЯ береХка в еловЯм темнЯм лесу, и вЯтерок уже заЯграл всеми ее листЯками.";
     break;
    case 4:
     text = "Полная грошёвых радостей жизнь.";
     break;
    case 5:
     text = "Мимо полисадников с рябиновыми кустами.";
     break;
    case 6:
     text = "Она паявлялась на ночном небасводе в разгаре лета, а с первым лучом сонца исчезала.";
     break;
    case 7:
     text = "Мы чясто ходим на соседний болшой прут. На лугу у пруда растут галубые незабутки.";
     break;
    case 8:
     text = "Этот человек кординально изменился.";
     break;
    case 9:
     text = "Извените, можно спросить?";
     break;
    case 10:
     text = "Комфорка была раскалена до предела.";
     break;
    case 11:
     text = "Я просто обажаю сладости.";
     break;
    case 12:
     text = "Я зашел на папулярный сайт Однокласники.";
     break;
    case 13:
     text = "На этот проэкт потребуется много времени.";
     break;
    case 14:
     text = "Это видио наберет много просмотров."; // Проблема с видио, если есть прецедент видимо в значении явно, заметно (устар.)
     break; // Папенька видимо поодобрел.
    case 15:
     text = "Винегред является моим любимым салатом.";
     break;
    case 16:
     text = "Муницыпальные выборы были перенесены на другое число.";
     break;
    case 17:
     text = "Время зделать правильный выбор.";
     break;
    case 18:
     text = "Только приступная власть боится умных и оброзованных людей!";
     break;
    case 19:
     text = "Мечты збываются.";
     break;
    case 20:
     text = "Это был неудачный эксперемент.";
     break;
    case 21: // Добавлена / пропущена буква
     text = "Есть у волшебницы Природы волшебный карандашь. Еще лежит снег. А она уже рисует в мечтах нежный белый ландышь, торопливую реч ручейка, роскош летних цветов, золотистую осеннюю рож.";
     break;
    case 22:
     text = "Сказка лож, да в ней намек! Добрым моладцам урок.";
     break;
    case 23:
     text = "Был устроен офицальный прием.";
     break;
    case 24:
     text = "Мне нужно в поликлиннику.";
     break;
    case 25:
     text = "Этот человек координально изменился.";
     break;
    case 26:
     text = "Он бы мог и не учавствовать в этой схватке.";
     break;
    case 27:
     text = "Она любит кататся на коньках.";
     break;
    case 28:
     text = "Агенство по продаже недвижимости.";
     break;
    case 29:
     text = "Скурупулёзный фотограф.";
     break;
    case 30:
     text = "Подскользнуться на льду очень легко.";
     break;
    case 31:
     text = "Програма исправления ошибок в предложении.";
     break;
    case 32:
     text = "Она любит ходить в кросовках.";
     break;
    case 33:
     text = "В дестве родители купили нам двухяросную кровать.";
     break;
    case 34:
     text = "Здраствуй, школа!";
     break;
    case 35:
     text = "Сегодня мы смотрели комедию Кавказкая пленица.";
     break;
    case 36:
     text = "Война и миръ.";
     break;
    case 37: // Слитное написание слов
     text = "Вобщем, дело сложное.";
     break;
    case 38:
     text = "Он неуспел растроится.";
     break;
    case 39:
     text = "Вопервых, нужно сделать уроки.";
     break;
    case 40:
     text = "Наконецто мы достигли цели.";
     break;
    case 41: // Переставлены буквы
     text = "Предже нам необходимо все расчитать.";
     break;
    case 42:
     text = "Ваше преосвящентсво";
     break;
    case 43: // Ошибочное словообразование
     text = "Равнодушество убивает";
     break;
    case 44:
     text = "Трудолюбимый";
     break;
    case 45:
     text = "Важный военоначальник";
     break;
    case 46: // Ошибочное образование формы прилагательного
     text = "Красивше выглядит";
     break;
    case 47:
     text = "Один брат был богатей другого.";
     break;
    case 48:
     text = "Соловей запел еще звончее.";
     break;
    case 49: // Ошибочное образование формы глагола
     text = "По вечерам я дремаю у телевизора.";
     break;
    case 50:
     text = "Мама всегда радовается гостям.";
     break;
    case 51:
     text = "Он ни разу не ошибился.";
     break;
    case 52:
     text = "Мы с братом отпиляем все лишние ветки, ставим елку на середину комнаты и украшиваем ее.";
     break;
    case 53: // Ошибочное образование формы деепричастия
     text = "Вышев на середину комнаты, он заговорил.";
     break;
    case 54: // Ошибочное образование формы существительного
     text = "Многие чуда техники";
     break;
    case 55: // Ошибочное образование формы числительного
     text = "Обоим сестрам";
     break;
    case 56: // Ошибочное образование формы местоимения
     text = "Ихние дети";
     break;
    case 57:
     text = "Я пошел к ему.";
     break;
    case 58: // Нарушение управления
     text = "Повествует читателей";
     break;
    case 59: // Нарушение способа выражения сказуемого в отдельных конструкциях
     text = "Все были рады, счастливы и весёлые.";
     break;
    case 60: // Нарушение согласования
     text = "Я знаком с группой ребят, увлекающимися джазом.";
     break;
    case 61:
     text = "Перед зеркалом сидел улыбающий ребенок.";
     break;
    case 62:
     text = "Это был самый ближайший путь.";
     break;
    case 63: // Нарушение связи между подлежащим и сказуемым
     text = "Кто это пришла?";
     break;
    case 64: // Разное
     text = "Крашеный недавно забор. Мальчик пила воду.";
     break;
    default:
     text = "Старик пасмотрел на карову сваю:" + Environment.NewLine
       + "– Зачем я, Бурёнка, тебя прадаю?" + Environment.NewLine
       + "Карову сваю не прадам никому –" + Environment.NewLine
       + "Такая скатина нужна самому!";
     break;
   }
   textBoxCheck.Text = text;
  }
  private void numericUpDownTestNumber_ValueChanged(object sender, EventArgs e)
  {
   testNumber = (int)numericUpDownTestNumber.Value;
   showText(testNumber);
   textBoxAfterCheck.Text = "";
   textBoxAfterCheck2.Text = "";
  }
  private void textBoxCheck_Leave(object sender, EventArgs e)
  {
   text = textBoxCheck.Text;
  }
 }
 public class Candidate : IComparable<Candidate>
 {
  public string CandidateName { get; set; }
  public int CandidateCode { get; set; }
  public int CandidateFactor { get; set; }
  public int CandidatePrecedentsCount { get; set; }
  // Компаратор по умолчанию - сортировка по возрастанию. Если поставить "-" перед this, то получим сортировку по убыванию
  public int CompareTo(Candidate compareCandidate)
  {
   return this.CandidateFactor.CompareTo(compareCandidate.CandidateFactor);
  }
 }
 public class Context : IEquatable<Context>
 {
  public int CandidateCode { get; set; }
  public int CandidateFactor { get; set; } // Число соседств
  public bool Equals(Context other)
  {
   if (other == null) return false;
   return (this.CandidateCode.Equals(other.CandidateCode));
  }
 }
}

Результаты тестрования

Таблица 1. Результаты тестирования приложения.
Для Word и Яндекс этап 1 – это выбор первого слова из списка кандидатов,
этап 2 – выбор лучшего слова из списка кандидатов

Текст с ошибкой / текст без ошибки Результаты тестированияЧисло ошибок
В текстеWordЯндексПриложение
Этапы
121212
ОРФОГРАФИЧЕСКИЕ ОШИБКИ
Замена буквы
1. Внизапно пашел снег. / 2
Внезапно пошел снег.
Word: без ошибок.
Яндекс-спеллер: без ошибок.
Приложение: без ошибок.
2000000
2. Прелетели грачи. / 1
Прилетели грачи.
Word: без ошибок.
Яндекс-спеллер: без ошибок.
Приложение: без ошибок.
1000000
3. Как зЯленое пламя, вспыхнулЯ береХка в еловЯм темнЯм лесу, и вЯтерок уже заЯграл всеми ее листЯками. / 8
Как зеленое пламя, вспыхнула березка в еловом темном лесу, и ветерок уже заиграл всеми ее листиками.
Word: Первое слово: Как зеленное пламя, вспыхнул бережка в еловыми теменям лесу, и ветерок уже заиграла всеми ее листками. / 7
Лучшее слово: Как зеленное пламя, вспыхнула Берёзка в еловом темными лесу, и ветерок уже заиграл всеми ее листиками. / 3
Яндекс-спеллер: вспыхнуло березка. / 1
Приложение: без ошибок.
8731100
4. Полная грошёвых радостей жизнь. / 1
Полная грошовых радостей жизнь
Word: без ошибок.
Яндекс-спеллер: Полная грошёвых радостей жизнь. / 1
Приложение: без ошибок.
1001100
5. Мимо полисадников с рябиновыми кустами. / 1
Мимо палисадников с рябиновыми кустами.
Word: без ошибок.
Яндекс-спеллер: без ошибок.
Приложение: без ошибок.
1000000
6. Она паявлялась на ночном небасводе в разгаре лета, а с первым лучом сонца исчезала. / 3
Она появлялась на ночном небосводе в разгаре лета, а с первым лучом солнца исчезала.
Word: Первое слово: лучом сенца исчезала. / 1
Лучшее слово: без ошибок.
Яндекс-спеллер: без ошибок.
Приложение: Этап 1: лучом конца. / 1
Этап 2: без ошибок.
310001/00
7. Мы чясто ходим на соседний болшой прут. На лугу у пруда растут галубые незабутки. / 5
Мы часто ходим на соседний большой пруд. На лугу у пруда растут голубые незабудки.
Word: большой прут... голубы незабудки. / 2
Яндекс-спеллер: без ошибок.
Приложение:
Этап 1: большой прут / 1
Этап 2: без ошибок.
522001/10
8. Этот человек кординально изменился. / 1
Этот человек кардинально изменился.
Word: без ошибок.
Яндекс-спеллер: без ошибок.
Приложение: без ошибок.
1000000
9. Извените, можно спросить? / 1
Извините, можно спросить?
Word: без ошибок.
Яндекс-спеллер: без ошибок.
Приложение: без ошибок.
1000000
10. Комфорка была раскалена до предела. / 1
Конфорка была раскалена до предела.
Word: Первое слово: Коморка была раскалена до предела. / 1
Лучшее слово: без ошибок.
Яндекс-спеллер: без ошибок.
Приложение:
Этап 1: Комфорта была раскалена до предела. / 1
Этап 2: без ошибок.
110001/00
11. Я просто обажаю сладости. / 1
Я просто обожаю сладости.
Word: без ошибок.
Яндекс-спеллер: без ошибок.
Приложение: без ошибок.
1000000
12. Я зашел на папулярный сайт Однокласники. / 2
Я зашел на популярный сайт Одноклассники.
Word: без ошибок.
Яндекс-спеллер: без ошибок.
Приложение: без ошибок.
2000000
13. На этот проэкт потребуется много времени. / 1
На этот проект потребуется много времени.
Word: без ошибок.
Яндекс-спеллер: без ошибок.
Приложение: без ошибок.
1000000
14. Это видио наберет много просмотров. / 1
Это видео наберет много просмотров.
Word: без ошибок.
Яндекс-спеллер: без ошибок.
Приложение: без ошибок.
Если есть прецедент видимо со значением явно, заметно, то может быть следующее:
Этап 1: Это видимо наберет много просмотров.
Этап 2: Что видимо наберет много просмотров.
1000000
15. Винегред является моим любимым салатом. / 1
Винегрет является моим любимым салатом.
Word: без ошибок.
Яндекс-спеллер: без ошибок.
Приложение: без ошибок.
1000000
16. Муницыпальные выборы были перенесены на другое число. / 1
Муниципальные выборы были перенесены на другое число.
Word: без ошибок.
Яндекс-спеллер: без ошибок.
Приложение: без ошибок.
1000000
17. Время зделать правильный выбор. / 1
Время сделать правильный выбор.
Word: Первое слово: Время заделать правильный выбор. / 1
Лучшее слово: без ошибок.
Яндекс-спеллер: без ошибок.
Приложение:
Этап 1: Время делать правильный выбор. / 1
Этап 2: без ошибок.
110001/00
18. Только приступная власть боится умных и оброзованных людей! / 2
Только преступная власть боится умных и образованных людей!
Word: приступная власть / 1
Яндекс-спеллер: без ошибок.
Приложение:
Этап 1: приступная власть / 1
Этап 2: без ошибок.
210001/10
19. Мечты збываются. /1
Мечты сбываются / забываются.
Word: Первое слово: Мечты забываются. / 0
Лучшее слово: без ошибок.
Яндекс-спеллер: без ошибок.
Приложение: без ошибок.
1000000
20. Это был неудачный эксперемент. / 1
Это был неудачный эксперимент.
Word: без ошибок.
Яндекс-спеллер: без ошибок.
Приложение: без ошибок.
1000000
Добавлена / пропущена буква
21. Есть у волшебницы Природы волшебный карандашь. Еще лежит снег. А она уже рисует в мечтах нежный белый ландышь, торопливую реч ручейка, роскош летних цветов, золотистую осеннюю рож. / 5
Есть у волшебницы Природы волшебный карандаш. Еще лежит снег. А она уже рисует в мечтах нежный белый ландыш, торопливую речь ручейка, роскошь летних цветов, золотистую осеннюю рожь.
Word: Первое слово: торопливую речи ручейка, роскоши летних цветов, золотистую осеннюю рож. / 3
Лучшее слово: осеннюю рож / 1
Яндекс-спеллер: осеннюю рож / 1
Приложение:
Этап 1: осеннюю рож / 1
Этап 2: без ошибок.
531111/10
22. Сказка лож, да в ней намек! Добрым моладцам урок. / 2
Сказка ложь, да в ней намек! Добрым молодцам урок.
Word: Сказка лож / 1
Яндекс-спеллер: без ошибок.
Приложение:
Этап 1: Сказка лож / 1
Этап 2: без ошибок.
211001/10
23. Был устроен офицальный прием. / 1
Был устроен официальный прием.
Word: без ошибок.
Яндекс-спеллер: без ошибок.
Приложение: без ошибок.
1000000
24. Мне нужно в поликлиннику. / 1
Мне нужно в поликлинику.
Word: без ошибок.
Яндекс-спеллер: без ошибок.
Приложение: без ошибок.
1000000
25. Этот человек координально изменился. / 1
Этот человек кардинально изменился.
Word: без ошибок.
Яндекс-спеллер: без ошибок.
Приложение:
Этап 1: координально изменился / 1
Этап 2: без ошибок.
100001/10
26. Он бы мог и не учавствовать в этой схватке. / 1
Он бы мог и не участвовать в этой схватке.
Word: Первое слово: Он бы мог и не учувствовать / 1
Лучшее слово: без ошибок.
Яндекс-спеллер: без ошибок.
Приложение: без ошибок
1100000
27. Она любит кататся на коньках. / 1
Она любит кататься на коньках.
Word: Первое слово: Она любит катятся на коньках. / 1
Лучшее слово: без ошибок.
Яндекс-спеллер: без ошибок.
Приложение:
Этап 1: любит катится / 1
Этап 2: без ошибок.
110001/00
28. Агенство по продаже недвижимости. / 1
Агентство по продаже недвижимости.
Word: без ошибок.
Яндекс-спеллер: без ошибок.
Приложение: без ошибок.
1000000
29. Скурупулёзный фотограф. / 1
Скрупулёзный фотограф.
Word: без ошибок.
Яндекс-спеллер: без ошибок.
Приложение: без ошибок.
1000000
30. Подскользнуться на льду очень легко. / 1
Поскользнуться на льду очень легко.
Word: без ошибок.
Яндекс-спеллер: Подскользнуться на льду / 1
Приложение:
Этап 1: Подскользнуться на льду / 1
Этап 2: без ошибок.
100111/10
31. Програма исправления ошибок в предложении. / 1
(программа и программ приоритет отдается программа)
Программа исправления ошибок в предложении.
Word: без ошибок.
Яндекс-спеллер: без ошибок.
Приложение: без ошибок.
1000000
32. Она любит ходить в кросовках. / 1
Она любит ходить в кроссовках.
Word: без ошибок.
Яндекс-спеллер: без ошибок.
Приложение: без ошибок.
1000000
33. В дестве родители купили нам двухяросную кровать. / 2
В детстве родители купили нам двухъярусную кровать.
Word: Первое слово: В действе / 1
Лучшее слово: без ошибок.
Яндекс-спеллер: без ошибок.
Приложение:
Этап 1: В детстве родители купили нам двухяросную кровать. двухяросную – нет в ТУС / 1
Этап 2: без ошибок.
210001/10
34. Здраствуй, школа! / 1
Здравствуй, школа!
Word: без ошибок.
Яндекс-спеллер: без ошибок.
Приложение: без ошибок.
1000000
35. Сегодня мы смотрели комедию Кавказкая пленица. / 2
Сегодня мы смотрели комедию Кавказская пленница.
Word: без ошибок.
Яндекс-спеллер: без ошибок.
Приложение:
Этап 1: Сегодня мы смотрели комедию Кавказская пленица. / 1
Этап 2: без ошибок.
200001/10
36. Война и миръ. / 1
Война и мир.
Word: без ошибок.
Яндекс-спеллер: без ошибок.
Приложение: без ошибок.
1000000
Слитное написание слов
37. Вобщем, дело сложное. / 1
В общем, дело сложное
Word: без ошибок.
Яндекс-спеллер: без ошибок.
Приложение: без ошибок
1000000
38. Он неуспел растроится. / 2
Он не успел расстроиться / застроиться.
Word: расстроится / 1
Яндекс-спеллер: без ошибок.
Приложение: Он не успел застроится. / 1
211001/01/0
39. Вопервых, нужно сделать уроки. / 1Word: без ошибок.
Яндекс-спеллер: Во первых / 1
Приложение: без ошибок.
1001100
40. Наконецто мы достигли цели. / 1
Наконец-то мы достигли цели.
Word: без ошибок.
Яндекс-спеллер: Наконец то / 1
Приложение: без ошибок.
1001100
Переставлены буквы
41. Предже нам необходимо все расчитать. / 1
Прежде нам необходимо все рассчитать.
Word: без ошибок.
Яндекс-спеллер: без ошибок.
Приложение: без ошибок.
1000000
42. Ваше преосвящентсво / 1
Ваше преосвященство
Word: без ошибок.
Яндекс-спеллер: без ошибок.
Приложение: без ошибок.
1000000
Разное
43. Старик пасмотрел на карову сваю:
– Зачем я, Бурёнка, тебя прадаю?
Карову сваю не прадам никому –
Такая скатина нужна самому! / 8
Старик посмотрел на корову свою:
– Зачем я, Буренка, тебя продаю?
Корову свою не продам никому –
Такая скотина нужна самому!
Word: сваю / 1
Яндекс-спеллер: без ошибок.
Приложение:
Этап 1: сваю / 1
Этап 2: без ошибок.
811001/10
ГРАММАТИЧЕСКИЕ ОШИБКИ
Ошибочное словообразование
44. Равнодушество убивает. / 1
Равнодушие убивает.
Word: Равнодушество / 1
Яндекс-спеллер: Равнодушество / 1
Приложение: Равнодушество / 1 / 0
111111/11/0
45. Трудолюбимый / 1
Трудолюбивый
Word: без ошибок.
Яндекс-спеллер: без ошибок.
Приложение: без ошибок.
1000000
46. Важный военоначальник. / 1
Важный военачальник.
Word: без ошибок.
Яндекс-спеллер: Первое слово: военноначальник / 1
Лучшее слово: без ошибок.
Приложение:
Этап 1: военоначальник / 1
Этап 2: без ошибок.
100101/10
Ошибочное образование формы прилагательного
47. Красивше выглядит / 1
Красивее выглядит
Word: Красившее выглядит. / 1
Яндекс-спеллер: Красивше выглядит. / 1
Приложение:
Этап 1: Красивые выглядит. / 1
Этап 2: без ошибок.
111111/00
48. Один брат был богатей другого. / 1
Один брат был богаче другого.
Word: Один брат был богатей другого. / 1
Яндекс-спеллер: Один брат был богатей другого. / 1
Приложение:
Этап 1: Один брат был богатей другого. / 1
Этап 2: без ошибок.
111111/10
49. Соловей запел еще звончее. / 1
Соловей запел еще звонче.
Word: без ошибок.
Яндекс-спеллер: без ошибок.
Приложение: без ошибок.
1000000
Ошибочное образование формы глагола
50. По вечерам я дремаю у телевизора. / 1
По вечерам я дремлю / дремал у телевизора.
Word: Первое слово: дрёмою / 1
Лучшее слово: дремал / 0
Яндекс-спеллер: без ошибок.
Приложение:
Этап 1: дремал / 0
Этап 2: без ошибок.
1100000
51. Мама всегда радовается гостям. / 1
Мама всегда радуется гостям.
Word: Первое слово: раздевается / 1
Лучшее слово: радоваться / 1
Яндекс-спеллер: радоваться / 1
Приложение: радоваться / 1 (ЦЗ > maxCost)
111111/11 / 0
52. Он ни разу не ошибился. / 1
Он ни разу не ошибся / ошибался.
Word: ошибался / 0
Яндекс-спеллер: Первое слово: ошибался / 0
Лучшее слово: без ошибок.
Приложение:
Этап 1: ошибался / 0
Этап 2: без ошибок.
1000000
53. Мы с братом отпиляем все лишние ветки, ставим елку на середину комнаты и украшиваем ее. / 2
Мы с братом отпиливаем все лишние ветки, ставим елку на середину комнаты и украшаем ее.
Word: Мы с братом отпылаем все лишние ветки, ставим елку на середину комнаты и окрашиваем ее. / 2
Яндекс-спеллер: Мы с братом отпиляем все лишние ветки, ставим елку на середину комнаты и окрашиваем ее. / 2
Приложение: Мы с братом отвиляем все лишние ветки, ставим елку на середину комнаты и окрашиваем ее. / 2 / 0
222222/22/0
Ошибочное образование формы деепричастия
54. Вышев на середину комнаты, он заговорил. / 1
Выйдя на середину комнаты, он заговорил.
Word: Первое слово: Вышив / 1
Лучшее слово: Вышел / 1
Яндекс-спеллер: Вышел / 1
Приложение: Вышел / 1
111111/11
Ошибочное образование формы существительного
55. Многие чуда техники / 1
Многие чудеса техники
Word: Многие чуда техники. / 1
Яндекс-спеллер: Многие чуда техники. / 1
Приложение:
Этап 1: Многие чуда техники. / 1
Этап 2: без ошибок.
111111/10
Ошибочное образование формы числительного
56. Обоим сестрам / 1
Обеим сестрам
Word: Обоим сестрам. / 1
Яндекс-спеллер: Обоим сестрам. / 1
Приложение:
Этап 1: Обоим сестрам. / 1
Этап 2: без ошибок.
111111/10
Ошибочное образование формы местоимения
57. Ихние дети / 1
Их дети
Word: Ихние дети / 1
Яндекс-спеллер: Ихние дети / 1
Приложение:
Этап 1: Ихние дети. / 1
Этап 2: Ихние дела. / 2 / 1
111111/12 / 1
58. Я пошел к ему. / 1
Я пошел к нему.
Word: Я пошел к ему. / 1
Яндекс-спеллер: без ошибок.
Приложение:
Этап 1: Я пошел к ему. / 1
Этап 2: Я хотел к ему. / 2 / 1
111111/12 / 1
Нарушение управления
59. Повествует читателей/ 1
Повествует читателям
Word: Повествует читателей/ 1
Яндекс-спеллер: Повествует читателей/ 1
Приложение:
Этап 1: Повествует читателей/ 1
Этап 2: без ошибок.
111111/10
Нарушение способа выражения сказуемого в отдельных конструкциях
60. Все были рады, счастливы и весёлые. / 1
Все были рады, счастливы и веселы.
Word: Все были рады, счастливы и весёлые. / 1
Яндекс-спеллер: Все были рады, счастливы и весёлые. / 1
Приложение:
Этап 1: и весёлые. / 1
Этап 2: без ошибок.
111111/10
Нарушение согласования
61. Я знаком с группой ребят, увлекающимися джазом. / 1
Я знаком с группой ребят, увлекающихся джазом.
Word: увлекающимися джазом / 1
Яндекс-спеллер: увлекающимися джазом / 1
Приложение:
Этап 1: увлекающимися джазом / 1
Этап 2: без ошибок.
111111/10
62. Перед зеркалом сидел улыбающий ребенок. / 1
Перед зеркалом сидел улыбающийся ребенок.
Word: без ошибок.
Яндекс-спеллер: без ошибок.
Приложение:
Этап 1: улыбающий ребенок / 1 (нет в ТУС)
Этап 2: без ошибок.
100001/10
63. Это был самый ближайший путь. / 1
Это был самый ближний путь.
Word: ближайший путь / 1
Яндекс-спеллер: ближайший путь / 1
Приложение: ближайший путь / 1
111111/11 / 0
Нарушение связи между подлежащим и сказуемым
64. Кто это пришла? / 1
Кто это пришел?
Word: Кто это пришла? / 1
Яндекс-спеллер: Кто это пришла? / 1
Приложение:
Этап 1: Кто это пришла? / 1
Этап 2: Кто это прошел? / 0
111111/10
Разное
65. Крашеный недавно забор. /
Крашенный недавно забор.
Мальчик пила воду.
Мальчик пил воду. / 2
Word: Крашеный недавно забор.
Мальчик пила воду. / 2
Яндекс-спеллер: Крашеный недавно забор.
Мальчик пила воду. / 2
Приложение:
Этап 1: Крашеный недавно забор.
Мальчик пила воду. / 2
Этап 2: без ошибок.
222222/20

Всего примеров: 65
Всего ошибок: 98
Из них:
Орфографических ошибок: 73
Грамматических ошибок: 25

Таблица 2. Итоги тестирования

ДействиеWordЯндекс-спеллерПриложение
Число неисправленных орфографических ошибок
Выбор 1-го кандидата /
автоматическая правка (этап 1) в случае Приложение
22614
Выбор из списка кандидатов969
Автоматическая правка (этап 2)--1
Выбор из списка кандидатов (этап 2)--0
Число неисправленных грамматических ошибок
Выбор 1-го кандидата /
автоматическая правка (этап 1) в случае Приложение
191920
Выбор из списка кандидатов181819
Автоматическая правка (этап 2)--10
Выбор из списка кандидатов (этап 2)--2
Всего неисправленных ошибок272411 / 2

Всего ошибок, полностью исправленных Приложением на этапе 1: 64 из 98.

Примеры приставок и суффиксов

Примеры приставок

Приставка – это значимая часть слова, которая находится перед корнем и служит для образования слов.

Приставка внутри слова: вибропреобразователь
пре – приставка,
вибр, образова – корни,
о – соединительная гласная,
тель – суффикс,
нулевое окончание,
вибропреобразователь – основа слова.

Две приставки: о-без-оружить, не-без-опасный, не-без-ызвестный, по-за-вчера, с-ыз-мала.

Приставки с дефисом: экс-министр.

Примеры суффиксов

Суффикс – это значимая часть слова, которая стоит после корня или после другого суффикса и служит для образования слов (словообразовательный суффикс) и для образования форм слова (формообразующий суффикс).
В группе словообразующих суффиксов выделяется постфикс (суффикс после окончания слова). Некоторые учебные издания выделяют нулевой суффикс.
Группы суффиксов:

  1. Словообразовательный суффикс:
  2. Формообразующий суффик.
  3. Нулевой суффикс.

Формообразующие суффиксы не входят в основу слова.

Суффиксы имен существительных

Словообразовательные суффиксы
Формообразующие суффиксы

Суффиксы имен прилагательных

Словообразовательные суффиксы

Служат для образования прилагательных от существительных:

Служат для образования прилагательных от глаголов:

Служат для образования прилагательных от других прилагательных:

Формообразующие суффиксы

Различать прилагательные и причастия:

крашеные (прил.) волосы – крашенные (причастие) хной волосы; тушёные (прил.) овощи – тушённые (причастие) в масле овощи.

Суффиксы причастий

Суффиксы являются словообразовательными.
Действительные причастия настоящего времени:

Запомнить:

брезжить – брезжущий;
зиждиться – зиждущийся;
мучить – мучащий, мучающий;
мерить – мерящий, меряющий.

Действительные причастия прошедшего времени:

Различать:

обессил-Е-ть (потерять силы) – обессилЕ-вш(ий),
обессил-И-ть (лишившийся кого-либо силы) – обессилИ-вш(ий).

Страдательные причастия настоящего времени:

Страдательные причастия прошедшего времени:

Различать:

Краш-енн(ый) (прич., есть зависимое слово) недавно забор.
НО: краш-ен(ый) (прил.) забор.

Суффиксы глаголов

Словообразовательные суффиксы
Формообразующие суффиксы

Нулевой суффикс – это признак бессуффиксального образования слова. Например: бег, Азов, вез-л(а) – вёз0 , сох-л(а) – сох0.

Суффиксы деепричастий

Являются словообразовательными.
Деепричастия совершенного вида:

Деепричастия несовершенного вида:

Суффиксы наречий

Словообразовательные суффиксы
Формообразующие суффиксы

Постфиксы

Постфикс – это словообразовательный суффикс, который в слове стоит после окончания или формообразующих суффиксов.

Глагольные постфиксы

Местоименные постфиксы

Отличать от частицы -то:
Я-то знаю куда надо идти.

Морфологические признаки глагола

Признаки глагола – это грамматические категории глагольных форм, которые присущи глаголу как части речи. В русском языке выделяют постоянные и непостоянные признаки глагола.

Постоянные признаки глагола

Постоянные признаки глагола – это грамматические категории, присущие всем глагольным формам (спрягаемым глаголам, инфинитиву, причастию, деепричастию).
Данные признаки не изменяются в зависимости от контекста, в котором употребляется глагол.

Непостоянные признаки глагола

Непостоянные признаки глагола – это грамматические категории, свойственные спрягаемым глаголам и причастиям. Данные категории изменяются в зависимости от контекста, в котором используется слово.

Имя существительное

Имя существительное – самостоятельная часть речи, которая обозначает предмет и отвечает на вопросы кто? что? Общее грамматическое значение – это значение предмета, то есть всего того, о чём можно сказать: это кто? или это что? Это единственная часть речи, которая может обозначать всё, что угодно, а именно:
1) названия конкретных вещей и предметов (дом, дерево, тетрадь, книга, портфель, кровать, лампа);
2) названия живых существ (человек, инженер, девочка, юноша, олень, комар);
3) названия различных веществ (кислород, бензин, свинец, сахар, соль);
4) названия различных явлений природы и общественной жизни (буря, мороз, дождь, праздник, война);
5) названия отвлечённых свойств и признаков (свежесть, белизна, синева);
6) названия отвлечённых действий и состояний (ожидание, убийство, бег).

Морфологические признаки имени существительного

Морфологические признаки имени существительного – это род, число, падеж, склонение.
Имена существительные

1) делятся на разряды
– по характеру лексического значения (собственные или нарицательные);
– по значению (конкретные, вещественные, отвлечённые (абстрактные) или собирательные);
– по типу (одушевленные или неодушевленные);
2) склоняются;
3) принадлежат к одному из четырёх родов – мужскому, женскому, среднему, общему, но не изменяются по родам: океан, река, море;
4) изменяются по числам: океан – океаны, река – реки, море – моря;
5) изменяются по падежам: океан – океана, океану, океаном и т.д.

Изменение по падежам и числам называется склонением.
Начальная форма существительного – именительный падеж единственного числа.
В предложении имена существительные чаще всего выступают как подлежащие или дополнения, но могут быть любыми другими членами предложения:

Книга делает человека хозяином вселенной (П. Павленко) – подлежащее; Вся жизнь человечества оседала в книге (А. Герцен) – дополнение; Книга – хранилище знаний (Б. Полевой) – именная часть составного сказуемого; Сырость от земли начинала холодить бок (А. Гайдар) – определение; Над седой равниной моря ветер тучи нагоняет (М. Лермонтов) – обстоятельство места; Не забудет народ-победитель беззаветных героев своих (В. Лебедев-Кумач) – приложение.
Существительное в предложении может выступать в роли обращения (не является членом предложения): Люся, я тебя жду!

Разряды имени существительного

По характеру лексического значения существительные делятся на два разряда:

1) нарицательные существительные – это существительные, которые называют класс однородных предметов: стол, мальчик, птица, весна;
2) собственные существительные – это существительные, которые называют единичные (индивидуальные) предметы, к которым относятся имена, отчества, фамилии людей, клички животных, названия городов, рек, морей, океанов, озёр, гор, пустынь (географические названия), названия книг, картин, кинофильмов, журналов, газет, спектаклей, названия кораблей, поездов, различных организаций, исторических событий и т.п.: Александр, Жучка, Россия, Астрахань, Волга, Байкал, «Капитанская дочка».

Примечание. Собственные имена существительные имеют ряд особенностей.

1) Имена собственные могут состоять из одного слова (Москва, Каспий, Кавказ, «Мцыри») или из нескольких слов (Нижний Новгород, Новый Орлеан, Василий Андреевич Жуковский, «Война и мир», Восточно-Сибирское море).
2) Имена собственные пишутся с большой буквы (Тула, Альпы).
3) Названия (заглавия) книг, газет, журналов, кинофильмов, картин, кораблей, поездов и т.п. пишутся с большой буквы и, кроме того, выделяются кавычками (роман «Евгений Онегин», картина «Утро в лесу», теплоход «Василий Суриков»).
4) Имена собственные не употребляются во множественном числе и не сочетаются с именами числительными (кроме случаев обозначения разных предметов и лиц, называющихся одинаково: У нас в классе две Иры и три Оли). Город Набережные Челны.
5) Собственные существительные могут переходить в нарицательные, а нарицательные – в собственные, например: Нарцисс (имя юноши-красавца в древнегреческой мифологии) – нарцисс (цветок); Бостон (город в США) – бостон (шерстяная ткань), бостон (медленный вальс), бостон (карточная игра); труд – газета «Труд».

По значению имена существительные делятся на четыре основных разряда:

По типу обозначаемых предметов существительные делятся на два разряда:

Примечание. Иногда бывает трудно разграничить одушевлённые и неодушевлённые существительные.

1) Одушевлёнными главным образом являются существительные мужского и женского родов. Одушевлённых существительных среднего рода очень мало (дитя, животное, лицо в значении «человек», млекопитающее, насекомое, страшилище, существо в значении «живой организм», чудовище).
2) Одушевлённые и неодушевлённые существительные имеют особенности в склонении:
у одушевлённых существительных во множественном числе форма винительного падежа совпадает с формой родительного падежа (у одушевлённых существительных мужского рода 2-го склонения и в единственном числе): В.п. мн.ч.= Р.п. мн.ч.
Ср.: мать – вижу матерей (мн.ч. В.п.), нет матерей (мн.ч. Р.п.); отец – вижу отцов (мн.ч. В.п.), нет отцов (мн.ч. Р.п.); вижу отца (ед.ч. В.п.), нет отца (ед.ч. Р.п.);
у неодушевлённых существительных во множественном числе форма винительного падежа совпадает с формой именительного падежа (у существительных мужского рода 2-го склонения и в единственном числе форма винительного падежа совпадает с формой именительного падежа): В.п. мн.ч. = И.п. мн.ч.
Ср.: страна – вижу страны (мн.ч. В.п.), здесь есть страны (мн.ч. И.п.); камень – вижу камни (мн.ч. В.п.), здесь есть камни (мн.ч. И.п.); вижу камень (ед.ч. В.п.), здесь есть камень (ед.ч. И.п.).
3) Деление существительных на одушевлённые и неодушевлённые не всегда совпадает с научным представлением о живой и неживой природе. Например, существительное полк обозначает совокупность людей, но это неодушевлённое существительное (В.п. = И.п.: вижу полк – здесь есть полк). То же самое можно наблюдать на примере существительного микроб. С точки зрения биологии, это часть живой природы, но существительное микроб неодушевлённое (В.п. = И.п.: вижу микроб – здесь есть микроб). Существительные мертвец и труп являются синонимами, но существительное мертвец является одушевлённым (В.п. = Р.п.: вижу мертвеца – нет мертвеца), а существительное труп является неодушевлённым (В.п. = И.п.: вижу труп – здесь есть труп).

Род имён существительных

Все существительные русского языка в форме единственного числа можно отнести к одному из следующих родов: мужскому, женскому, среднему, общему.

Как определить род имени существительного

Род существительного можно определить, согласовав с ним местоимение мой:
мой сын, мой воевода, мой занавес, мой домишко
– мужской род; моя жена, моя стена, моя ночь – женский род, моё окно, моё небо, моё животное – средний род.
У большинства существительных, обозначающих людей, род можно определить по полу: мой подмастерье, мой дедушка (мужской род); моя мать, моя сестра (женский род).
Род существительных определяется по форме единственного числа. Существительные, употребляемые только во множественном числе, рода не имеют: ясли, макароны, брюки, вилы.

Какие существительные относятся к общему роду

Существительные общего рода – это существительные, которые характеризуют человека, дают ему оценочную характеристику; они имеют окончания -а, -я и относятся к 1-му склонению: неряха, заводила, запевала, работяга, грязнуля, стиляга, пьяница, неженка, соня, плакса.
Существительные общего рода могут обозначать людей и мужского, и женского пола: Какой ты неряха! Какая ты неряха!

Как определить род неизменяемых существительных

Род неизменяемых существительных, называющих людей, определяется по полу: храбрый идальго, изысканная леди.
Существительные, обозначающие профессии и род занятий, относятся к мужскому роду: военный атташе, ночной портье. Существительные 2-го склонения с нулевым окончанием, называющие лиц по профессии (врач, профессор, доцент, шофёр и т.д.), даже если используются по отношению к лицам женского пола, всё же являются существительными мужского рода.
Неизменяемые существительные, называющие животных, относятся к мужскому роду, хотя при указании на самку могут употребляться как существительные женского рода: австралийский кенгуру, смешной шимпанзе; шимпанзе кормила своих детёнышей. Исключения: цеце (муха), иваси (рыба) – женский род.
Неизменяемые неодушевлённые существительные относятся к среднему роду: ночное такси, вкусное рагу, новое жалюзи, ароматное какао, выдержанное бордо, пьянящее шардоне, горячее капучино, локомотивное депо, новое пальто, плетеное кашпо. Исключения: кофе, пенальти, сирокко (мужской род); авеню, салями (женский род).
Род иноязычных географических названий определяется по родовому слову: далекое Монако (это княжество, т.е. существительное среднего рода, значит, слово Монако тоже среднего рода), широкая Лимпопо (река – ж.р.), густонаселенный Токио (город – м.р.). Если можно использовать два разных родовых слова, то возможны варианты согласования: независимое Гаити (государство – с.р.), независимая Гаити (страна – ж.р.) и далекий Гаити (остров – м.р.); прекрасный Брешиа (город – м.р.) и прекрасная Брешиа (провинция – ж.р.). В некоторых случаях родовая принадлежность существительного устанавливается традицией, поэтому требуется словарная проверка.

Как определить род сложносокращенных слов (аббревиатур)

Род аббревиатур обычно определяют по опорному слову в расшифровке аббревиатуры или же по родовому слову: НАТО (альянс – м.р.) постановил, МГУ (университет – м.р.) принял новых студентов, СНГ (содружество – с.р.) выступило с инициативой, ЮНЕСКО (организация – ж.р.) объявила 2011 год годом лесов.
В некоторых случаях родовая принадлежность существительного устанавливается традицией, поэтому требуется словарная проверка: вуз (опорное слово – заведение, но род мужской), МИД (опорное слово – министерство, но род мужской), ТАСС (опорное слово – агентство, но род мужской).

Как определить род существительных, оканчивающихся на -ЛЬ в форме им. п.

(Слова типа тюль, мозоль, полироль, толь, вентиль.)
Род таких слов надо запоминать, в случае затруднений проверять по словарям.
К мужскому роду относятся слова аэрозоль, полироль, пасквиль, водевиль, квантиль, квартиль, эндшпиль, тюль, толь, бемоль и др.
К женскому роду относятся такие слова, как антресоль, мозоль, канифоль, вакуоль, триоль и др.

Как определить род существительных, обозначающих названия обуви и парных предметов

Род таких слов надо запоминать, в случае затруднений проверять по словарям.
Слова, обозначающие названия обуви:

Ботинки – один ботинок
Боты – один бот
Ботфорты – один ботфорт
Кеды – один кед
Сланцы – один сланец
Мокасины – один мокасин
Босоножки – одна босоножка
Туфли – одна туфля
Сандалии – одна сандалия
Тапки – одна тапка
Кроссовки – одна кроссовка
Бутсы – одна бутса
Бахилы – одна бахила
Вьетнамки – одна вьетнамка

Кроме этого, существует двуродовое существительное унты. Если во мн.ч. ударение падает на окончание слова (унты, -ов), то форма единственного числа – один унт. Если же во мн.ч. ударение падает на основу (унты), то форма им.п. ед.ч. – унта.
Другие слова, обозначающие названия парных предметов: гамаши – одна гамаша, гетры – одна гетра, бакенбарды – одна бакенбарда, краги – одна крага. Но: гольфы – один гольф, рельсы – один рельс, коррективы – один корректив.

Как определить род составных существительных

(Слова типа кафе-столовая, диван-кровать.)
В случае если у существительного изменяется по падежам только одна часть, род определяется по изменяемой части: персональная интернет-страничка (ж.р.). Если же у существительного изменяются обе части слова, то род определяется по более значимой по смыслу части: вкусный торт-мороженое (м.р.), удобное кресло-кровать (с.р.).

Изменяются ли имена существительные по родам?

Имена существительные по родам не изменяются, род у каждого существительного – категория постоянная: мама – только ж.р., яблоко – только с.р. и т.д.

Склонение имён существительных

Склонение – это изменение имён существительных (и других именных частей речи) по падежам и числам.
В русском языке

ПадежВопросы падежей
Именительныйкто? что?
Родительныйкого? чего?
Дательныйкому? чему?
Винительныйкого? что?
Творительныйкем? чем?
Предложныйо ком? о чём?

Как определить падеж имён существительных (и других именных частей речи)

Чтобы определить падеж имени существительного, нужно задать к нему вопрос от слова, к которому это существительное относится: думаю (о ком?) о маме, нет (чего?) дождя.
Затем надо, используя таблицу «Падежи. Вопросы падежей» (см. выше), посмотреть, какому падежу соответствует заданный вопрос: думаю (о ком?) о маме – предложный падеж; нет (чего? ) дождя – родительный падеж.

Примечания:

Каждому падежу соответствуют два вопроса (первый – для одушевлённых существительных, второй – для неодушевлённых).
Названия падежей и падежные вопросы следует заучить, поскольку умение определять падеж – одно из важнейших базовых умений для изучающих русский язык.

Как определить склонение имён существительных

Все существительные можно разделить на семь групп, у которых будут одинаковые окончания (формы) при склонении по падежам и числам, т.е. существует семь типов склонения существительных:

1-е склонениеСуществительные женского, мужского и общего рода с окончаниями -а, -явесна, земля, линия, дядя, владыка, грязнуля
2-е склонениеСуществительные мужского рода с нулевым окончаниемдом, край, мяч, планетарий
Все существительные с окончаниями -о, -еокно, поле, подозрение – с.р.; волчище, подмастерье – м.р.
3-е склонениеСуществительные женского рода с нулевым окончаниеммать, дочь, ночь, степь
Разносклоняемые существительные (имеют окончания разных склонений)десять существительных среднего рода на -мя (окончание -я); существительные путь, дитявремя, бремя, стремя, племя, пламя (полымя – устар.), знамя, темя, семя, имя, вымя; путь, дитя

Чтобы определить склонение имени существительного, его надо поставить в начальную форму (т.е. в именительный падеж единственного числа) и определить, к какому типу склонения из семи вышеназванных это существительное относится.
Если существительное не имеет формы единственного числа, то оно не относится ни к одному из типов склонения: сани, брюки, ножницы.
Примечания:
Существительное человек имеет разные корни в единственном и множественном числе (человек – люди), поэтому имеет разные типы склонения в единственном и множественном числе:
человек (единственное число) – склоняется как существительное 2-го склонения; люди (множественное число) – склоняется как существительное 3-го склонения.
Большинство существительных распределяются по первым трём типам склонения.
Типы склонения следует заучить, поскольку умение определять склонение – одно из базовых умений для изучающих русский язык.

Образцы склонения имён существительных

1-е склонение

ПадежЕдинственное числоМножественное число
И. п.МамаНяняАрияМамыНяниАрии
Р. п.МамыНяниАрииМамНяньАрий
Д. п.МамеНянеАрииМамамНянямАриям
В. п.МамуНянюАриюМамНяньАрии
Т. п.Мамой(-ою)Няней(-ею)Арией(-ею)МамамиНянямиАриями
П. п.О мамеО нянеОб арииО мамахО няняхОб ариях

2-е склонение. Мужской род

ПадежЕдинственное числоМножественное число
И. п.ДомКоньКийДомаКониКии
Р. п.ДомаКоняКияДомовКонейКиев
Д. п.ДомуКонюКиюДомамКонямКиям
В. п.ДомКоняКийДомаКонейКии
Т. п.ДомомКонёмКиемДомамиКонямиКиями
П. п.О домеО конеОб кииО домахО коняхОб киях

2-е склонение. Средний род

ПадежЕдинственное числоМножественное число
И. п.ОкноМореЗданиеОкнаМоряЗдания
Р. п.ОкнаМоряЗданияОконМорейЗданий
Д. п.ОкнуМорюЗданиюОкнамМорямЗданиям
В. п.ОкноМореЗданиеОкнаМоряЗдания
Т. п.ОкномМоремЗданиемОкнамиМорямиЗданиями
П. п.Об окнеО мореО зданииОб окнахО моряхО зданиях

3-е склонение

ПадежЕдинственное числоМножественное число
И. п.НочьНочи
Р. п.НочиНочей
Д. п.НочиНочам
В. п.НочьНочи
Т. п.НочьюНочами
П. п.О ночиО ночах

Разносклоняемые существительные

ПадежЕдинственное числоМножественное число
И. п.ВремяПутьВременаПути
Р. п.ВремениПутиВремёнПутей
Д. п.ВремениПутиВременамПутям
В. п.ВремяПутьВременаПути
Т. п.ВременемПутёмВременамиПутями
П. п.О времениО путиО временахО путях

Морфологические признаки прилагательного

Морфологические признаки имени прилагательного – это ряд грамматических категорий, свойственных словам данной части речи. Морфологические признаки определяют особенности согласования прилагательных с существительными и местоимениями, а также указывают на оттенки значения конкретного слова.
Примеры форм прилагательных в словосочетаниях: новый учебник, синее море, детская площадка, арбузный аромат, девочка весела, камень тверд, эти мяч лучше, эта статья интереснейшая.
В русском языке выделяют постоянные и непостоянные признаки прилагательных.
Постоянные признаки являются неизменяемыми, изначально присущими прилагательными. Непостоянные признаки изменяются в зависимости от речевой ситуации и при согласовании с существительными и местоимениями.

Постоянные признаки прилагательных

  1. Разряд по значению.
  2. Полнота-краткость формы (только у качественных).
  3. Степень сравнения (только у качественных).

Непостоянные признаки прилагательных

  1. Род.
  2. Число.
  3. Падеж (только у полных).
    Примеры: спелыми яблоками, о спелых яблоках, учебных пособий, учебным пособиям.

Морфологические признаки причастия

Причастие – самостоятельная часть речи (в некоторых источниках особая форма глагола), которая обозначает признак по действию и отвечает на вопросы Какой? Что делающий? Что делавший? Каков?
Морфологические признаки причастия – ряд грамматических категорий, которые присущи данной части речи и позволяют ее отличать от других словоформ.
В русском языке выделяют постоянные и непостоянные признаки причастий. Как глаголы, причастия имеют время, залог, вид и возвратность; как прилагательные – изменяются по родам, числам и падежам, согласуются с существительными и местоимениями.
Начальной формой причастий является полная форма единственного числа, именительного падежа, мужского рода.
Примеры: изучаемый, свернутый, идущий, знавший, припрятанный.

Постоянные признаки причастий

Непостоянные признаки причастий

Полные причастия изменяются по родам, числам и падежам, могут входить в состав причастного оборота. Краткие – только по родам и числам.

Морфологические признаки числительного

Имя числительное очень активно используется в повседневной жизни. Чтобы правильно пользоваться числительными, необходимо хорошо знать весь раздел морфологии русского языка, посвящённый ему.
Для этой части речи характерно несколько грамматических категорий, которые могут быть постоянными и непостоянными. Первая группа признаков – это грамматические категории, которые свойственны числительным независимо от их формы. Непостоянные признаки – это категории, которые могут приобретаться или теряться числительным в процессе их употребления в речи.

Постоянные признаки числительных

К постоянным признакам числительного относятся:

Количественные числительные могут любого разряда по строению.
Порядковые числительные могут простыми, сложными и составными.
Собирательные числительные могут быть только простыми.

Непостоянные признаки числительных

Непостоянные признаки числительных – это род, число и падеж (см. табл. 1).
Количественные и собирательные числительные не изменяются по родам и числам.
Исключения:
Род:
Количественные простые числительные: два – две; один – одна – одно; тысяча (ж. р.), миллион, миллиард и др. число с несколькими нолями (м. р.).
Количественные составные числительные: числа, которые заканчиваются на слова один, два. Например: восемьдесят два карандаша (м. р.) – восемьдесят две тетради ж. р.); семьдесят одна страница (ж. р.) – семьдесят одно слово (ср. р.).
Собирательные числительные: оба брата, обе стены.
Число:
Количественные простые числительные: один (ед. ч.) – одни (мн. ч.); тысяча (ед. ч.) – тысячи (мн. ч.), миллион (ед. ч.) – миллионы (мн. ч.) и др. числа с несколькими нулями.

Примеры изменения по родам порядковых числительных:
Простые: женск. (первая любовь), муж. (первый поцелуй), ср. (первое разочарование).
Сложные: женск. (пятидесятая колонна), муж. (пятидесятый столб), ср. (пятидесятое здание).
Составные: женск. (сорок первая глава), муж. (сорок первый год), ср. (сорок первое стихотворение).

Примеры изменения по числам порядковых числительных:
Простые: второй сорт (ед. ч.) – вторые сутки (мн. ч.).
Сложные: семидесятый километр (ед. ч.) – семидесятые годы (мн. ч.).
Составные: двадцать восьмой вопрос (ед. ч.) – двадцать восьмые двери (мн. ч.).

Примеры изменения числительных по падежам:
Количественные простые: пять баллов (И. п.) – пяти баллов (Р. п.); три толстяка (И. п.) – трёх толстяков (Р. п.).
Количественные сложные: триста спартанцев (И. п.) – трёхсот спартанцев (Р. п).
Количественные составные: двадцать семь конфет (И. п.) – о двадцати семи конфетах (П. п.); семьсот пленных (И. п.) – семьюстами пленными (Т. п.).
Количественные дробные: три четвёртых (И. п.) – трёх четвёртых (Р. п.);
шесть девятых (И. п.) – шестью девятыми (Т. п.).
Порядковые простые: девятый вал (И. п.) – девятым валом (Т. п.); первая любовь (И. п.) – О первой любви (П. п.); доброе слово (И. п.) – в добром слове (П. п.); смелые бойцы (И. п.) – смелым бойцам (Д. п.).
Порядковые сложные: девяностое поколение (И. п.) – девяностым поколением (Р. п.); шестидесятая процедура (И. п.) – шестидесятой процедуре (Д. п.); двухсотое предупреждение (И. п.) – двухсотым предупреждением (Т. п.).
Порядковые составные: тридцать третий символ (И. п.) – тридцать третьему символу (Д. п.); двадцать девятая строка (И. п.) – двадцать девятую строку (В. п.).
Собирательные: двое котят (И. п.) – двоим котятам (Д. п.).

Морфологические признаки наречия

Наречие – самостоятельная неизменяемая часть речи, которая отвечает на вопросы Как? Где? Куда? Когда? Почему? Зачем? Сколько? и обозначает признак действия, предмета или другого признака. В русском языке выделяют постоянные и непостоянные морфологические признаки наречий.
Наречия не спрягаются и не склоняются (не изменяются по числам, родам и падежам), поэтому в большинстве своем имеют только постоянные грамматические признаки. Непостоянный признак (степень сравнения) выделяют при морфологическом разборе только у определительных качественных наречий.

Постоянные признаки наречий

Разряд по значению

Разряд по функции

Непостоянные признаки наречий

Степень сравнения наречий (только у определительных качественных наречий).

Морфологические признаки междометия

Междометие является особой, уникальной частью речи. Она лишь указывает на эмоции и чувства, конкретно не называя их, подобно тому, как местоимение указывает на предметы и признаки. Поскольку междометие не имеет определённого значения и не отвечает на конкретные вопросы, оно не может относиться к самостоятельным частям речи. Нельзя назвать его служебной частью речи, поскольку оно не связывает частей предложения или слов в словосочетании.
Междометие является неизменяемой частью речи, поэтому не имеет временных морфологических признаков. Зато у него есть постоянные признаки. К ним относятся:

Морфологический разбор слов

Морфология – раздел науки о языке, который изучает слово как часть речи. При морфологическом разборе определяют, какие у слова:

Морфологические признаки бывают постоянные и непостоянные. У неизменяемых частей речи непостоянные признаки отсутствуют.
Синтаксическая роль слова определяется по контексту.

План морфологического разбора существительного

1) начальная форма (в именительном падеже, единственном числе);
2) собственное или нарицательное;
3) одушевленное или неодушевленное;
4) род;
5) склонение;
6) число;
7) падеж;
8) роль в предложении.

Пример. Малыши любят пить молоко.
Молоко – существительное, начальная форма – молоко, нарицательное, неодушевленное, среднего рода, 2-го склонения, в винительном падеже, единственном числе (множественного не имеет), прямое дополнение.

План морфологического разбора глагола

1) инфинитив (начальная форма);
2) возвратный или невозвратный;
3) переходный или непереходный;
4) вид;
5) спряжение;
6) наклонение;
7) время (для изъявительного наклонения);
8) лицо (для настоящего, будущего времени и повелительного наклонения);
9) род (для прошедшего времени и условного наклонения в единственном числе);
10) число;
11) роль в предложении.

Пример. Сказали правду, не побоявшись осуждения.
Сказали – глагол, начальная форма – сказать, невозвратный, непереходный, совершенного вида, 1-го спряжения, в изъявительном наклонении, прошедшем времени, множественном числе, является сказуемым.

План морфологического разбора прилагательного

1) начальная форма – инфинитив (именительный падеж, единственное число);
2) разряд (качественное, относительное или притяжательное);
3) краткое или полное (только о качественном);
4) степень сравнения (только о качественном);
5) род (только о единственном числе);
6) падеж;
7) число;
8) роль в предложении.

Пример. Полное лукошко грибов собрала Аленушка.
Полное – имя прилагательное, начальная форма – полный; качественное: полное; в положительной (нулевой) степени сравнения, в среднем роде, винительном падеже, является дополнением.

План морфологического разбора причастия

1) начальная форма (именительный падеж, единственное число, мужской род);
2) инфинитив;
3) вид;
4) время;
5) возвратное или невозвратное (для действительного);
6) переходное или непереходное (для действительного);
7) полное или краткое (для страдательного);
8) род (для единственного числа);
9) падеж;
10) число;
11) роль в предложении.

Пример. Гляжу на опадающую листву и грущу.
Опадающую – причастие, начальная форма – опадающий, от глагола опадать, несовершенного вида, настоящего времени, невозвратное, непереходное, в женском роде, винительном падеже, единственном числе, согласованное определение.

План морфологического разбора деепричастия

1) глагол, от которого образовано;
2) вид;
3) возвратное или невозвратное;
4) переходное или непереходное;
5) роль в предложении.

Пример. Уезжая за границу, ты грустишь о доме.
Уезжая – деепричастие, от глагола «уезжать», несовершенного вида, невозвратное, непереходное, обстоятельство образа действия.

План морфологического разбора числительного

1) начальная форма (именительный падеж для количественного, именительный падеж, единственное число, мужской род – для порядкового);
2) разряд по значению (количественное, порядковое);
3) разряд по составу (простое, сложное, составное);
4) падеж;
5) род и число (у порядковых и некоторых количественных);
6) роль в предложении.

Пример. Пролетело четыре дня.
Четыре – числительное, начальная форма – четыре, количественное, простое, в именительном падеже, не имеет числа и рода, является подлежащим.

План морфологического разбора наречия

1) разряд по значению (определительное или обстоятельственное);
2) степень сравнения (если есть).

Пример. Солнце взошло выше, и тучи рассеялись.
Выше – наречие, обстоятельственное места, является обстоятельством места, сравнительная степень.

План морфологического разбора местоимения

1) начальная форма (именительный падеж, единственное число, если изменяется по числам и родам);
2) разряд по значению;
3) род (если есть);
4) падеж;
5) число (если есть);
6) роль в предложении.

Пример. С нее капали хрустальные дождинки.
Нее – местоимение, начальная форма – она, личное, 3-е лицо, женский род, родительный падеж, единственное число, обстоятельство места.

План морфологического разбора междометия

1) часть речи;
2) морфологические признаки: разряд по структуре, значению и по происхождению;
3) синтаксическая роль.

Примеры.
Ишь ты, какая цаца.
Ишь ты – междометие; простое, эмоциональное, выражает ощущение досады, производное. Не играет в предложении никакой роли.
«Спасибо, я не люблю мороженое», – ответила девочка равнодушно.
Спасибо – междометие; простое, этикетное, производное. Не играет в предложении никакой роли.
«Вон отсюда!» – в бешенстве закричал старик.
Вон – междометие; простое, эмоциональное, выражает волю говорящего, производное. Не играет никакой роли в предложении.
Ой, как больно!
Ой – междометие; простое, эмоциональное, выражает негативные эмоции, непроизводное. Не играет никакой роли в предложении.

Морфемный разбор слова

План разбора

План разбора слова по составу состоит в следующем:

  1. Определяем, к какой части речи относится анализируемое слово.
  2. Выделяем окончание и основу. Для определения окончания слово изменяют, например, по падежам. Изменяемая часть будет являться окончанием, остальная часть слова без окончания – основой. Следует помнить, что всё слово может представлять собой основу без окончания, например у наречия – неизменяемой части речи.
  3. Определяем, входит ли в основу слова кроме корня также приставка и суффикс. Для этого слово сопоставляется с однокоренными словами.
  4. Убеждаемся, что выделенные приставки и суффиксы имеются в других словах. Для проверки подбираются аналогичные слова и сравниваются с анализируемым.
  5. Обозначаем части слова с помощью графических обозначений.

Примеры разборов:
метро – неизменяемое существительное, нет окончания;
лес – существительное с нулевым окончанием;
пришкольный – прилагательное со всеми основными морфемами: приставкой, корнем, суффиксом, окончанием;
ледокол – существительное с двумя корнями и соединительной гласной;
позвала – глагол с приставкой, окончанием, словообразующим суффиксом -а и формообразующим суффиксом -л, который не входит в основу;
быстро – наречие с суффиксом, не имеет окончания.

Морфемный разбор деепричастия

Деепричастия являются неизменяемой частью речи, поэтому при разборе по составу у них не выделяют окончания. Формообразующими суффиксами деепричастий являются – -а/-я, -в/-вши/-ши.

Примеры морфемного разбора:
Назвавшись другом.
На-зв-а-вши-сь – производное от глагола «назваться»; основа – назвавшись, приставка – на-, корень – -зв-, суффиксы – -а-, -вши-, постфикс – -сь.
Читая книгу.
Чит-а-я – производное от глагола «читать»; основа – читая, корень – -чит-, суффиксы – -а-, -я.
Подбросив мяч.
Под-брос-и-в – производное от глагола «подбросить»; основа – подбросив, приставка – под-, корень – -брос-, суффиксы – -и-, -в-.

Приложения

Загруженные книги

Приводится список прроизведений, использованных для формирования таблицы соседей.

  1. Пушкин Александр Сергеевич.
  2. Лермонтов Михаил Юрьевич. Герой нашего времени.
  3. Чехов Антон Павлович. Анна на шее.
  4. Гоголь Николай Васильевич. Мертвые души.
  5. Толстой Лев Николаевич.
  6. Достоевский Федор Михайлович. Преступление и наказание.
  7. Платонов Андрей Платонович. Усомнившийся Макар.
  8. Островский Николай Алексеевич. Как закалялась сталь.
  9. Шолохов Михаил Александрович. Поднятая целина.
  10. Катаев Валентин Петрович. Белеет парус одинокий.
  11. Твардовский Александр Трифонович. Василий Теркин.
  12. Распутин Валентин Григорьевич. Прощание с Матерой.
  13. Проханов Александр Анддреевия. Путин, в которого мы верили.
  14. Русские народные сказки.
  15. Михалков Сергей Владимирович.
  16. Гайдар Аркадий Петрович.Тимур и его команда.
  17. Бианки Виталий Валентинович.
  18. Успенский Эдуард Николаевич.
  19. Марк Твен. Приключения Тома Сойера.

Создание и редактирование таблиц базы данных

Создание таблиц

CREATE TABLE [CrPr].[dbo].[other_words] -- Союз, ввод, межд, предик, част, предл, мест, нар,мест
(
    code int NOT NULL
)

CREATE TABLE [CrPr].[dbo].[pronouns_a] -- Прл,мест
(
    code int NOT NULL,
    plural bit,
    gender char(3),
    wcase char(4),
    soul bit,
)

CREATE TABLE [CrPr].[dbo].[pronouns_n] -- Сущ,мест
(
    code int NOT NULL,
    plural bit,
    gender char(3),
    wcase char(4)
)

CREATE TABLE [CrPr].[dbo].[pretexts]
(
    code int NOT NULL,
    wcase char(4) NOT NULL
)

CREATE TABLE [CrPr].[dbo].[numerals]
(
    code int NOT NULL,
    type_sub char(5),
    wcase char(4),
    gender char(3),
    soul bit NOT NULL,
    plural bit NOT NULL
)

CREATE TABLE [CrPr].[dbo].[participles]
(
    code int NOT NULL,
    time char(4),
    transit char(6),
    perfect bit,
    vozv bit
)

CREATE TABLE [CrPr].[dbo].[communions]
(
    code int NOT NULL,
    wcase char(4),
    time char(4),
    transit char(6),
    perfect bit,
    vozv bit,
    gender char(3),
    plural bit NOT NULL
)

CREATE TABLE [CrPr].[dbo].[adjectives]
(
    code int NOT NULL,
    wcase char(4) NOT NULL,
    short bit NOT NULL,
    gender char(3) NOT NULL,
    plural bit NOT NULL,
    comp char(5)
)

CREATE TABLE [CrPr].[dbo].[verbs]
(
    code int NOT NULL,
    transit char(6),
    perfect bit,
    face char(4),
    time char(4),
    kind char(4),
    vozv bit,
    nakl char(3),
    inf bit,
    plural bit,
    gender char(3)
)

Создаем all_words_dist2 с code int PRIMARY KEY IDENTITY NOT NULL:

CREATE TABLE all_words_dist2 (
    code int PRIMARY KEY IDENTITY NOT NULL,
    word char(30) NOT NULL,
)

Вставка данных в таблицы

Глаголы (verbs):

INSERT INTO [CrPr].[dbo].[verbs]
SELECT [code], [transit], [perfect], [face], [time], [kind], [vozv], [nakl], [inf], [plural], [gender] FROM [CrPr].[dbo].[words] WHERE [type] = 'гл'

Наречия (adverbs):

INSERT INTO [CrPr].[dbo].[adverbs] SELECT [code], [type_sub], [type_ssub] FROM [CrPr].[dbo].[words] WHERE [type] = 'нар'

Существительные (nouns):

INSERT INTO [CrPr].[dbo].[nouns] SELECT [code], [gender], [wcase], [soul], [plural] FROM [CrPr].[dbo].[words] WHERE [type] = 'сущ'

Все слова (all_words):

INSERT INTO [CrPr].[dbo].[all_words] SELECT [word], [code], [code_parent], [type] FROM [CrPr].[dbo].[words]

Прилагательные (adjectives):

INSERT INTO [CrPr].[dbo].[adjectives] SELECT code, wcase, short, gender, plural, comp FROM [CrPr].[dbo].[words] WHERE [type] = 'прл'

Причастия (communions):

INSERT INTO [CrPr].[dbo].[communions] SELECT code, wcase, time, transit, perfect, vozv, gender, plural FROM [CrPr].[dbo].[words] WHERE [type] = 'прч'

Деепричастия (participles):

INSERT INTO [CrPr].[dbo].[participles] SELECT code, time, transit, perfect, vozv FROM [CrPr].[dbo].[words] WHERE [type] = 'дееп'

Числительные (numerals):

INSERT INTO [CrPr].[dbo].[numerals] SELECT code, type_sub, wcase, gender, soul, plural FROM [CrPr].[dbo].[words] WHERE [type] = 'числ'

Предлоги (pretexts):

INSERT INTO [CrPr].[dbo].[pretexts] SELECT code, wcase FROM [CrPr].[dbo].[words] WHERE [type] = 'предл' Сущ,мест (pronouns_n):

INSERT INTO [CrPr].[dbo].[pronouns_n] SELECT code, plural, gender, wcase FROM [CrPr].[dbo].[words] WHERE [type] = 'сущ,мест'

Прл,мест (pronouns_a):

INSERT INTO [CrPr].[dbo].[pronouns_a] SELECT code, plural, gender, wcase, soul FROM [CrPr].[dbo].[words] WHERE [type] = 'прл,мест'

Союз, ввод, межд, предик, част, предл, мест, нар,мест (other_words):

INSERT INTO [CrPr].[dbo].[other_words] SELECT code FROM [CrPr].[dbo].[words]
WHERE [type] in ('cоюз', 'ввод', 'межд', 'предик', 'част', 'предл', 'мест', 'нар,мест')

Перенос данных из одной таблицы в другую

Переносим all_words_dist в all_words_dist2:

SET IDENTITY_INSERT dbo.all_words_dist2 ON;
GO
insert into all_words_dist2 (word, code) select word, code from all_words_dist --where code >= 100

Очистка таблицы

DELETE FROM [CrPr].[dbo].[verbs]

DELETE FROM [CrPr].[dbo].[freq] where len(trim([word])) = 1

Число записей в таблице и максимальное значение кода

SELECT count([code]) FROM [CrPr].[dbo].[all_words]

SELECT max(code) FROM all_words -- 4257382

Создание индекса

CREATE INDEX word ON [CrPr].[dbo].all_words (word)

CREATE INDEX [type] ON [CrPr].[dbo].all_words (type)

CREATE unique INDEX root ON [CrPr].[dbo].roots (root)

Сжатие log-файла с предварительным изменением модели восстановления базы данных на SIMPLE

USE [dbname];
GO
-- Truncate the log by changing the database recovery model to SIMPLE.
ALTER DATABASE [dbname]
SET RECOVERY SIMPLE;
GO
-- Shrink the truncated log file to 1 MB.
DBCC SHRINKFILE ([dbname_Log], 1);
GO
-- Reset the database recovery model.
ALTER DATABASE [dbname]
SET RECOVERY FULL;
GO

Запросы и программы на SQL

Примеры запросов

1. Выбор слов, заканчивающихся на 'ся'

SELECT [word], [type]
    FROM [CrPr].[dbo].[all_words]
    WHERE right(trim(word), 2) = 'ся'
    and TYPE not in ('прч', 'гл')

2. Выбор слов, заканчивающихся на 'т'

SELECT [word], [type]
    FROM [CrPr].[dbo].[all_words]
    WHERE right(trim(word), 1) = 'т'
    and TYPE not in ('сущ', 'гл')

3. Запрос с группировкой и сортировкой

SELECT word, count(word) as cnt
    FROM CrPr.dbo.freq
    GROUP BY word
    ORDER BY cnt

4. Сортировка по убыванию

SELECT word, count(word) as cnt
    FROM CrPr.dbo.freq
    GROUP BY word
    ORDER BY cnt DESC

5. Выбор записей одной длины

SELECT TOP 20 word, freq FROM freq WHERE len(trim(word)) = 6

Выбор во временную таблицу

drop table #tmp -- При повторном выборе
select word, code_neighbor, neighbourhood into #tmp
    from all_words_dist, neighbors where all_words_dist.code = neighbors.code
select #tmp.word, all_words_dist.word as neighbor, neighbourhood
    from #tmp, all_words_dist where all_words_dist.code = #tmp.code_neighbor
    order by neighbourhood

Изменение значений

UPDATE freq SET word = 'рыба' WHERE word = '..ыба'

Удаление поcледних добавленных слов из таблиц правки текста

Применяется для удаления последних добавленных записей, если они были добавлены в результате разбора текста, содержащего ошибки.

delete FROM all_words_dist where code > 4274202
go
delete FROM new_words where code > 4274202
go
delete FROM neighbors where code > 4274202
go
delete FROM neighbors where code_neighbor > 4274202

Удаление слов, имеющих ошибки, по имени и кодам

Применяется, если было добавлено слово с ошибкой.

--Удаление слова с ошибкой по имени слова
declare @code int, @word varchar(30)
set @word = 'полисадников'
set @code = (select code from all_words_dist where word = @word)
print @code
delete from all_words_dist where code = @code
delete from new_words where code = @code
delete from neighbors where code = @code
delete from neighbors where code_neighbor = @code

Применяется, если были добавлены слова с ошибками.

-- Удаление слов, имеющих ошибки, по их кодам
-- 4277298 – mатроскин
delete FROM all_words_dist where code in (4277298, 4276999, 4277803)
go
delete FROM new_words where code in (4277298, 4276999, 4277803)
go
delete FROM neighbors where code in (4277298, 4276999, 4277803)
go
delete FROM neighbors where code_neighbor in (4277298, 4276999, 4277803)

Определение частоты присутствия слов из списка в таблице соседей

declare @words table (word varchar(30))
-- Слова, имеющиеся в таблице слов без повторов
insert into @words values('крова')
insert into @words values('кровка')
insert into @words values('кровав')
insert into @words values('кровам')
insert into @words values('корова')
insert into @words values('какова')
insert into @words values('каров')
insert into @words values('карпов')
insert into @words values('кадров')
insert into @words values('икаров')
--
declare cur cursor for select word from @words
open cur
declare @code int, @f1 int, @f2 int, @k int
declare @word varchar(30)
fetch next from cur into @word
while @@FETCH_STATUS = 0
begin
    set @code = (SELECT code FROM all_words_dist where word = @word)
    if @code IS NOT NULL
    begin
        set @f1 = (SELECT sum(neighbourhood) as f1
            FROM [CrPr].[dbo].[neighbors] where code = @code group by code)
        set @f2 = (SELECT sum(neighbourhood) as f2
            FROM [CrPr].[dbo].[neighbors] where code_neighbor = @code group by code_neighbor)
        if @f1 + @f2 > 0
            print @word + ': ' + ltrim(str(@f1 + @f2, 12))
    end
    else
    begin
        print 'Not found'
    end
    fetch next from cur into @word
end
close cur
deallocate cur
go

Число правых соседств предшествующего слова и число левых соседств следующего слова

declare @word varchar(30), @wordLeft varchar(30), @wordRight varchar(30), @code int
declare @text varchar(200)
set @text = lower('Многие чудеса техники')
declare split_cur cursor Local fast_forward for
    select * from string_split(@text, ' ')
open split_cur
fetch next from split_cur into @wordLeft
fetch next from split_cur into @word
fetch next from split_cur into @wordRight
print @wordLeft + ' ' + @word + ' ' + @wordRight
select code from all_words_dist where word = @word -- Для контроля
set @code = (select code from all_words_dist where word = @word)
print @code
-- @word - текущее слово
-- @code - код текущего слова
-- Число правых соседств предшествующего слова @wordLeft
select word, neighbourhood from all_words_dist, neighbors
    where all_words_dist.code = neighbors.code and code_neighbor = @code and word = @wordLeft
-- Число левых соседств следующего слова @wordRight
select neighbourhood, word from all_words_dist, neighbors
    where all_words_dist.code = neighbors.code_neighbor and neighbors.code = @code and word = @wordRight
close split_cur
deallocate split_cur

Число строк в таблице слов-соседей (ТСС), в которых есть заданное слово

declare @word varchar(30)
set @word = 'корова'
set @code = (SELECT code FROM all_words_dist where word = @word)
if @code IS NOT NULL
    set @f1 = (SELECT count(neighbourhood) as f1
        FROM [CrPr].[dbo].[neighbors] where code = @code group by code)
    set @f2 = (SELECT count(neighbourhood) as f2
        FROM [CrPr].[dbo].[neighbors] where code_neighbor = @code group by code_neighbor)
    print @word + ': ' + ltrim(str(@f1 + @f2, 12))

Правые и левые соседи слова

--Правые соседи слова
declare @word varchar(30), @code int
set @word = 'солнца'
set @code = (SELECT code FROM [CrPr].[dbo].[all_words_dist] where word = @word)
select word from [CrPr].[dbo].[all_words_dist], [CrPr].[dbo].[neighbors]
    where all_words_dist.code = code_neighbor and neighbors.code = @code
    order by word

--Левые соседи слова
declare @word varchar(30), @code int
set @word = 'солнца'
set @code = (SELECT code FROM [CrPr].[dbo].[all_words_dist] where word = @word)
select word from [CrPr].[dbo].[all_words_dist], [CrPr].[dbo].[neighbors]
    where all_words_dist.code = neighbors.code and neighbors.code_neighbor = @code
    order by word

Заполнение таблицы allprecedents (всего прецедентов)

--Поле leftprecedents
declare cur cursor
    for select code, sum(neighbourhood) as leftprecedents FROM [CrPr].[dbo].[neighbors] group by code
open cur
declare @code int, @code_cur int, @neighbors smallint, @leftprecedents smallint
fetch next from cur into @code_cur, @neighbors
while @@FETCH_STATUS = 0
begin
    set @leftprecedents = (SELECT leftprecedents FROM allprecedents where code = @code_cur)
    if @leftprecedents IS NULL
        begin
            insert into allprecedents (code, leftprecedents, rightprecedents) values (@code_cur, @neighbors, 0)
        end
    else
        begin
            if @leftprecedents = 0
                begin
                    update allprecedents set leftprecedents = @neighbors where code = @code_cur
                end
        end
    fetch next from cur into @code_cur, @neighbors
end
close cur
deallocate cur

--Поле rightprecedents
declare cur cursor
    for select code_neighbor, sum(neighbourhood) as rightprecedents FROM [CrPr].[dbo].[neighbors] group by code_neighbor
open cur
declare @code int, @code_cur int, @neighbors smallint, @rightprecedents smallint
fetch next from cur into @code_cur, @neighbors
while @@FETCH_STATUS = 0
begin
    set @rightprecedents = (SELECT rightprecedents FROM allprecedents where code = @code_cur)
    if @leftprecedents IS NULL
        begin
            insert into allprecedents (code, leftprecedents, rightprecedents) values (@code_cur, 0, @neighbors)
        end
    else
        begin
            if @rightprecedents = 0
                begin
                    update allprecedents set rightprecedents = @neighbors where code = @code_cur
                end
        end
    fetch next from cur into @code_cur, @neighbors
end
close cur
deallocate cur

Всего соседств (проверка заполнения neighbors)

--Правые соседи (левые прецеденты)
select sum(neighbourhood) FROM [CrPr].[dbo].[neighbors] where code = 4292430 group by code
--Левые соседи (правые прецеденты)
select sum(neighbourhood) FROM [CrPr].[dbo].[neighbors] where code_neighbor = 4292430 group by code_neighbor

Пересечение контекстов (левого и правого)

declare @wordLeft varchar(30), @codeLeft int, @wordRight varchar(30), @codeRight int, @word varchar(30)
set @wordLeft = 'просто'
set @wordRight = 'она'
set @codeLeft = (SELECT code FROM [CrPr].[dbo].[all_words_dist] where word = @wordLeft)
set @codeRight = (SELECT code FROM [CrPr].[dbo].[all_words_dist] where word = @wordRight)
declare cur cursor
    for select code_neighbor FROM [CrPr].[dbo].[neighbors] where code = @codeLeft
open cur
declare @code int, @n int, @n2 int
set @n = 0
fetch next from cur into @code
while @@FETCH_STATUS = 0
begin
    set @n2 = (SELECT count(code) FROM neighbors where code = @code and code_neighbor = @codeRight)
    if @n2 > 0
    begin
        set @n = @n + @n2
        set @word = (select word from all_words_dist where code = @code)
        print @word + ' : ' + str(@n2)
    end
    fetch next from cur into @code
end
close cur
deallocate cur
print str(@n)

Выбор и удаление повторяющихся слов таблицы freq

Таблица freq содержит частотный словарь лемм русского языка.

-- Выбор повторяющихся слов (они определены другим запросом)
SELECT word, freq
    FROM CrPr.dbo.freq
where word in ('буль-буль', 'позади', 'будто', 'небось', 'минус', 'хотя', 'рядовой', 'словно', 'иначе', 'на', 'взамен', 'всего', 'благо', 'видать', 'виновный', 'полицейский', 'ишь', 'участковый', 'тепло', 'подряд', 'едва', 'охота', 'приезжий', 'печь', 'пора', 'хромой', 'часовой', 'исключительно', 'вдоль', 'вокруг', 'дежурный', 'добро', 'свыше', 'малость', 'беда', 'против', 'нет', 'прежде', 'все-таки', 'хоть', 'немало', 'ученый', 'ведь', 'внутрь', 'один', 'главное', 'военный', 'больше', 'пожарный', 'прямо', 'относительно', 'раненый', 'сзади', 'верующий', 'се', 'это', 'рабочий', 'соответственно', 'больной', 'напасть', 'напротив', 'ближний', 'весть', 'спящий', 'сродни', 'простой', 'сколько', 'вон', 'там', 'накануне', 'во', 'несколько', 'пленный', 'угодно', 'взрослый', 'присяжный', 'мало', 'пропасть', 'здорово', 'после', 'пол', 'просто', 'стать', 'правда', 'хорошо', 'плюс', 'пьяный', 'знакомый', 'дак', 'новорожденный', 'надо', 'выходной', 'слепой', 'впереди', 'белый', 'подчиненный', 'только', 'ага', 'мертвый', 'то-то', 'когда', 'нищий', 'вахтенный', 'пасть', 'умирающий', 'влюбленный', 'управляющий', 'лень', 'немного', 'ниже', 'поперек', 'русский', 'лишь', 'покойный', 'ни', 'более', 'даже', 'право', 'посередине', 'че', 'ли', 'старший', 'вообще-то', 'блин', 'фон', 'выше', 'вслед', 'согласно', 'вблизи', 'так', 'неизвестно', 'да', 'блатной', 'столько', 'же', 'конечно', 'уж', 'честь', 'весь', 'уполномоченный', 'ладно', 'марш', 'что-то', 'внутри', 'присутствующий', 'святой', 'лучше', 'однако', 'грех', 'умерший', 'убитый', 'пусть', 'ведущий', 'еще', 'мимо', 'глухой', 'смертный', 'поди', 'зло', 'нет-нет', 'как', 'все', 'спасибо', 'точно', 'много', 'пока', 'вроде', 'ровно', 'то', 'раз', 'что')
order by word

-- Удаляем повторы. Из всех повторов остается слово с наибольшим значением freq
delete FROM [CrPr].[dbo].[freq] where word = 'ага' and freq = 4.3
GO
delete FROM [CrPr].[dbo].[freq] where word = 'беда' and freq = 7.3
GO
delete FROM [CrPr].[dbo].[freq] where word = 'белый' and freq = 5.9
GO
delete FROM [CrPr].[dbo].[freq] where word = 'благо' and freq = 10.0
GO
delete FROM [CrPr].[dbo].[freq] where word = 'блатной' and freq = 3.3
GO
delete FROM [CrPr].[dbo].[freq] where word = 'ближний' and freq = 9.9
GO
delete FROM [CrPr].[dbo].[freq] where word = 'блин' and freq = 10.1
GO
delete FROM [CrPr].[dbo].[freq] where word = 'более' and freq = 179.2
GO
delete FROM [CrPr].[dbo].[freq] where word = 'больной' and freq = 71.0
GO
delete FROM [CrPr].[dbo].[freq] where word = 'больше' and freq = 218.7
GO
delete FROM [CrPr].[dbo].[freq] where word = 'будто' and freq = 168.5
GO
delete FROM [CrPr].[dbo].[freq] where word = 'буль-буль' and freq = 3.3
GO
delete FROM [CrPr].[dbo].[freq] where word = 'вахтенный' and freq = 2.9
GO
delete FROM [CrPr].[dbo].[freq] where word = 'вблизи' and freq = 5.3
GO
delete FROM [CrPr].[dbo].[freq] where word = 'вдоль' and freq = 4.1
GO
delete FROM [CrPr].[dbo].[freq] where word = 'ведущий' and freq = 10.3
GO
delete FROM [CrPr].[dbo].[freq] where word = 'ведь' and freq = 219.9
GO
delete FROM [CrPr].[dbo].[freq] where word = 'верующий' and freq = 7.6
GO
delete FROM [CrPr].[dbo].[freq] where word = 'весть' and freq = 5.3
GO
delete FROM [CrPr].[dbo].[freq] where word = 'весь' and freq = 8.2
GO
delete FROM [CrPr].[dbo].[freq] where word = 'взамен' and freq = 5.6
GO
delete FROM [CrPr].[dbo].[freq] where word = 'взрослый' and freq = 43.4
GO
delete FROM [CrPr].[dbo].[freq] where word = 'видать' and freq = 11.2
GO
delete FROM [CrPr].[dbo].[freq] where word = 'виновный' and freq = 7.4
GO
delete FROM [CrPr].[dbo].[freq] where word = 'влюбленный' and freq = 4.8
GO
delete FROM [CrPr].[dbo].[freq] where word = 'внутри' and freq = 40.4
GO
delete FROM [CrPr].[dbo].[freq] where word = 'внутрь' and freq = 9.8
GO
delete FROM [CrPr].[dbo].[freq] where word = 'во' and freq = 7.1
GO
delete FROM [CrPr].[dbo].[freq] where word = 'военный' and freq = 35.5
GO
delete FROM [CrPr].[dbo].[freq] where word = 'вокруг' and freq = 72.7
GO
delete FROM [CrPr].[dbo].[freq] where word = 'вон' and freq = 18.6
GO
delete FROM [CrPr].[dbo].[freq] where word = 'вообще-то' and freq = 5.6
GO
delete FROM [CrPr].[dbo].[freq] where word = 'впереди' and freq = 13.3
GO
delete FROM [CrPr].[dbo].[freq] where word = 'вроде' and freq = 78.5
GO
delete FROM [CrPr].[dbo].[freq] where word = 'вроде' and freq = 7.1
GO
delete FROM [CrPr].[dbo].[freq] where word = 'все' and freq = 7.2
GO
delete FROM [CrPr].[dbo].[freq] where word = 'все' and freq = 433.3
GO
delete FROM [CrPr].[dbo].[freq] where word = 'всего' and freq = 5.0
GO
delete FROM [CrPr].[dbo].[freq] where word = 'все-таки' and freq = 4.4
GO
delete FROM [CrPr].[dbo].[freq] where word = 'вслед' and freq = 5.7
GO
delete FROM [CrPr].[dbo].[freq] where word = 'выходной' and freq = 15.2
GO
delete FROM [CrPr].[dbo].[freq] where word = 'выше' and freq = 2.6
GO
delete FROM [CrPr].[dbo].[freq] where word = 'главное' and freq = 82.0
GO
delete FROM [CrPr].[dbo].[freq] where word = 'глухой' and freq = 2.7
GO
delete FROM [CrPr].[dbo].[freq] where word = 'грех' and freq = 4.8
GO
delete FROM [CrPr].[dbo].[freq] where word = 'да' and freq = 787.5
GO
delete FROM [CrPr].[dbo].[freq] where word = 'даже' and freq = 260.6
GO
delete FROM [CrPr].[dbo].[freq] where word = 'дак' and freq = 4.8
GO
delete FROM [CrPr].[dbo].[freq] where word = 'дежурный' and freq = 17.9
GO
delete FROM [CrPr].[dbo].[freq] where word = 'добро' and freq = 3.9
GO
delete FROM [CrPr].[dbo].[freq] where word = 'едва' and freq = 15.8
GO
delete FROM [CrPr].[dbo].[freq] where word = 'еще' and freq = 85.5
GO
delete FROM [CrPr].[dbo].[freq] where word = 'же' and freq = 77.7
GO
delete FROM [CrPr].[dbo].[freq] where word = 'здорово' and freq = 8.8
GO
delete FROM [CrPr].[dbo].[freq] where word = 'зло' and freq = 16.1
GO
delete FROM [CrPr].[dbo].[freq] where word = 'знакомый' and freq = 71.3
GO
delete FROM [CrPr].[dbo].[freq] where word = 'иначе' and freq = 41.2
GO
delete FROM [CrPr].[dbo].[freq] where word = 'исключительно' and freq = 25.2
GO
delete FROM [CrPr].[dbo].[freq] where word = 'ишь' and freq = 5.1
GO
delete FROM [CrPr].[dbo].[freq] where word = 'как' and freq = 10.3
GO
delete FROM [CrPr].[dbo].[freq] where word = 'как' and freq = 2212.7
GO
delete FROM [CrPr].[dbo].[freq] where word = 'когда' and freq = 138.4
GO
delete FROM [CrPr].[dbo].[freq] where word = 'конечно' and freq = 20.8
GO
delete FROM [CrPr].[dbo].[freq] where word = 'ладно' and freq = 22.3
GO
delete FROM [CrPr].[dbo].[freq] where word = 'лень' and freq = 7.8
GO
delete FROM [CrPr].[dbo].[freq] where word = 'ли' and freq = 106.9
GO
delete FROM [CrPr].[dbo].[freq] where word = 'лишь' and freq = 2.6
GO
delete FROM [CrPr].[dbo].[freq] where word = 'лучше' and freq = 5.8
GO
delete FROM [CrPr].[dbo].[freq] where word = 'мало' and freq = 135.8
GO
delete FROM [CrPr].[dbo].[freq] where word = 'малость' and freq = 3.8
GO
delete FROM [CrPr].[dbo].[freq] where word = 'марш' and freq = 3.0
GO
delete FROM [CrPr].[dbo].[freq] where word = 'мертвый' and freq = 15.1
GO
delete FROM [CrPr].[dbo].[freq] where word = 'мимо' and freq = 75.9
GO
delete FROM [CrPr].[dbo].[freq] where word = 'минус' and freq = 2.7
GO
delete FROM [CrPr].[dbo].[freq] where word = 'много' and freq = 84.0
GO
delete FROM [CrPr].[dbo].[freq] where word = 'много' and freq = 14.5
GO
delete FROM [CrPr].[dbo].[freq] where word = 'на' and freq = 3.5
GO
delete FROM [CrPr].[dbo].[freq] where word = 'надо' and freq = 12.8
GO
delete FROM [CrPr].[dbo].[freq] where word = 'накануне' and freq = 15.9
GO
delete FROM [CrPr].[dbo].[freq] where word = 'напасть' and freq = 4.3
GO
delete FROM [CrPr].[dbo].[freq] where word = 'напротив' and freq = 23.2
GO
delete FROM [CrPr].[dbo].[freq] where word = 'небось' and freq = 4.6
GO
delete FROM [CrPr].[dbo].[freq] where word = 'неизвестно' and freq = 2.7
GO
delete FROM [CrPr].[dbo].[freq] where word = 'немало' and freq = 7.2
GO
delete FROM [CrPr].[dbo].[freq] where word = 'немного' and freq = 28.8
GO
delete FROM [CrPr].[dbo].[freq] where word = 'несколько' and freq = 88.2
GO
delete FROM [CrPr].[dbo].[freq] where word = 'нет' and freq = 589.2
GO
delete FROM [CrPr].[dbo].[freq] where word = 'нет-нет' and freq = 5.0
GO
delete FROM [CrPr].[dbo].[freq] where word = 'ни' and freq = 543.5
GO
delete FROM [CrPr].[dbo].[freq] where word = 'ниже' and freq = 7.0
GO
delete FROM [CrPr].[dbo].[freq] where word = 'нищий' and freq = 12.2
GO
delete FROM [CrPr].[dbo].[freq] where word = 'новорожденный' and freq = 4.3
GO
+delete FROM [CrPr].[dbo].[freq] where word = 'один' and freq = 529.5
GO
delete FROM [CrPr].[dbo].[freq] where word = 'однако' and freq = 35.7
GO
delete FROM [CrPr].[dbo].[freq] where word = 'относительно' and freq = 20.6
GO
delete FROM [CrPr].[dbo].[freq] where word = 'охота' and freq = 7.4
GO
delete FROM [CrPr].[dbo].[freq] where word = 'пасть' and freq = 11.8
GO
delete FROM [CrPr].[dbo].[freq] where word = 'печь' and freq = 8.7
GO
delete FROM [CrPr].[dbo].[freq] where word = 'пленный' and freq = 3.3
GO
delete FROM [CrPr].[dbo].[freq] where word = 'плюс' and freq = 19.0
GO
delete FROM [CrPr].[dbo].[freq] where word = 'поди' and freq = 5.9
GO
delete FROM [CrPr].[dbo].[freq] where word = 'подряд' and freq = 3.7
GO
delete FROM [CrPr].[dbo].[freq] where word = 'подчиненный' and freq = 8.5
GO
delete FROM [CrPr].[dbo].[freq] where word = 'пожарный' and freq = 6.2
GO
delete FROM [CrPr].[dbo].[freq] where word = 'позади' and freq = 12.7
GO
delete FROM [CrPr].[dbo].[freq] where word = 'пока' and freq = 213.4
GO
delete FROM [CrPr].[dbo].[freq] where word = 'пока' and freq = 2.8
GO
delete FROM [CrPr].[dbo].[freq] where word = 'покойный' and freq = 5.5
GO
delete FROM [CrPr].[dbo].[freq] where word = 'пол' and freq = 15.9
GO
delete FROM [CrPr].[dbo].[freq] where word = 'полицейский' and freq = 12.7
GO
delete FROM [CrPr].[dbo].[freq] where word = 'поперек' and freq = 5.6
GO
delete FROM [CrPr].[dbo].[freq] where word = 'пора' and freq = 71.0
GO
delete FROM [CrPr].[dbo].[freq] where word = 'посередине' and freq = 5.0
GO
delete FROM [CrPr].[dbo].[freq] where word = 'после' and freq = 11.9
GO
delete FROM [CrPr].[dbo].[freq] where word = 'правда' and freq = 175.5
GO
delete FROM [CrPr].[dbo].[freq] where word = 'право' and freq = 7.6
GO
delete FROM [CrPr].[dbo].[freq] where word = 'прежде' and freq = 87.1
GO
delete FROM [CrPr].[dbo].[freq] where word = 'приезжий' and freq = 4.4
GO
delete FROM [CrPr].[dbo].[freq] where word = 'присутствующий' and freq = 3.8
GO
delete FROM [CrPr].[dbo].[freq] where word = 'присяжный' and freq = 5.3
GO
delete FROM [CrPr].[dbo].[freq] where word = 'пропасть' and freq = 19.8
GO
delete FROM [CrPr].[dbo].[freq] where word = 'просто' and freq = 82.6
GO
delete FROM [CrPr].[dbo].[freq] where word = 'простой' and freq = 4.8
GO
delete FROM [CrPr].[dbo].[freq] where word = 'против' and freq = 18.1
GO
delete FROM [CrPr].[dbo].[freq] where word = 'прямо' and freq = 118.0
GO
delete FROM [CrPr].[dbo].[freq] where word = 'пусть' and freq = 32.2
GO
delete FROM [CrPr].[dbo].[freq] where word = 'пьяный' and freq = 8.1
GO
delete FROM [CrPr].[dbo].[freq] where word = 'рабочий' and freq = 64.2
GO
delete FROM [CrPr].[dbo].[freq] where word = 'раз' and freq = 65.0
GO
delete FROM [CrPr].[dbo].[freq] where word = 'раз' and freq = 5.1
GO
delete FROM [CrPr].[dbo].[freq] where word = 'раненый' and freq = 9.7
GO
delete FROM [CrPr].[dbo].[freq] where word = 'ровно' and freq = 3.8
GO
delete FROM [CrPr].[dbo].[freq] where word = 'ровно' and freq = 3.3
GO
delete FROM [CrPr].[dbo].[freq] where word = 'русский' and freq = 75.7
GO
delete FROM [CrPr].[dbo].[freq] where word = 'рядовой' and freq = 6.9
GO
delete FROM [CrPr].[dbo].[freq] where word = 'свыше' and freq = 6.2
GO
delete FROM [CrPr].[dbo].[freq] where word = 'святой' and freq = 23.7
GO
delete FROM [CrPr].[dbo].[freq] where word = 'се' and freq = 2.9
GO
delete FROM [CrPr].[dbo].[freq] where word = 'сзади' and freq = 3.0
GO
delete FROM [CrPr].[dbo].[freq] where word = 'сколько' and freq = 50.9
GO
delete FROM [CrPr].[dbo].[freq] where word = 'слепой' and freq = 7.2
GO
delete FROM [CrPr].[dbo].[freq] where word = 'словно' and freq = 29.9
GO
delete FROM [CrPr].[dbo].[freq] where word = 'смертный' and freq = 5.5
GO
delete FROM [CrPr].[dbo].[freq] where word = 'согласно' and freq = 5.0
GO
delete FROM [CrPr].[dbo].[freq] where word = 'соответственно' and freq = 3.5
GO
delete FROM [CrPr].[dbo].[freq] where word = 'спасибо' and freq = 23.3
GO
delete FROM [CrPr].[dbo].[freq] where word = 'спасибо' and freq = 43.9
GO
delete FROM [CrPr].[dbo].[freq] where word = 'спящий' and freq = 2.8
GO
delete FROM [CrPr].[dbo].[freq] where word = 'сродни' and freq = 3.2
GO
delete FROM [CrPr].[dbo].[freq] where word = 'старший' and freq = 11.4
GO
delete FROM [CrPr].[dbo].[freq] where word = 'стать' and freq = 31.8
GO
delete FROM [CrPr].[dbo].[freq] where word = 'столько' and freq = 54.3
GO
delete FROM [CrPr].[dbo].[freq] where word = 'так' and freq = 5.8
GO
delete FROM [CrPr].[dbo].[freq] where word = 'там' and freq = 51.9
GO
delete FROM [CrPr].[dbo].[freq] where word = 'тепло' and freq = 23.7
GO
delete FROM [CrPr].[dbo].[freq] where word = 'то' and freq = 108.7
GO
delete FROM [CrPr].[dbo].[freq] where word = 'то' and freq = 902.4
GO
delete FROM [CrPr].[dbo].[freq] where word = 'только' and freq = 109.0
GO
delete FROM [CrPr].[dbo].[freq] where word = 'то-то' and freq = 4.4
GO
delete FROM [CrPr].[dbo].[freq] where word = 'точно' and freq = 34.2
GO
delete FROM [CrPr].[dbo].[freq] where word = 'точно' and freq = 25.9
GO
delete FROM [CrPr].[dbo].[freq] where word = 'убитый' and freq = 10.1
GO
delete FROM [CrPr].[dbo].[freq] where word = 'угодно' and freq = 28.5
GO
delete FROM [CrPr].[dbo].[freq] where word = 'уж' and freq = 106.2
GO
delete FROM [CrPr].[dbo].[freq] where word = 'умерший' and freq = 5.4
GO
delete FROM [CrPr].[dbo].[freq] where word = 'умирающий' and freq = 3.1
GO
delete FROM [CrPr].[dbo].[freq] where word = 'уполномоченный' and freq = 8.6
GO
delete FROM [CrPr].[dbo].[freq] where word = 'управляющий' and freq = 12.1
GO
delete FROM [CrPr].[dbo].[freq] where word = 'участковый' and freq = 7.0
GO
delete FROM [CrPr].[dbo].[freq] where word = 'ученый' and freq = 22.7
GO
delete FROM [CrPr].[dbo].[freq] where word = 'фон' and freq = 12.3
GO
delete FROM [CrPr].[dbo].[freq] where word = 'хорошо' and freq = 52.9
GO
delete FROM [CrPr].[dbo].[freq] where word = 'хоть' and freq = 87.4
GO
delete FROM [CrPr].[dbo].[freq] where word = 'хотя' and freq = 88.9
GO
delete FROM [CrPr].[dbo].[freq] where word = 'хромой' and freq = 2.8
GO
delete FROM [CrPr].[dbo].[freq] where word = 'часовой' and freq = 9.8
GO
delete FROM [CrPr].[dbo].[freq] where word = 'че' and freq = 5.5
GO
delete FROM [CrPr].[dbo].[freq] where word = 'честь' and freq = 4.1
GO
delete FROM [CrPr].[dbo].[freq] where word = 'что' and freq = 121.2
GO
delete FROM [CrPr].[dbo].[freq] where word = 'что' and freq = 3810.2
GO
delete FROM [CrPr].[dbo].[freq] where word = 'что' and freq = 2.7
GO
delete FROM [CrPr].[dbo].[freq] where word = 'что-то' and freq = 8.7
GO
delete FROM [CrPr].[dbo].[freq] where word = 'это' and freq = 466.7

Литература

  1. Исправление ошибок в слове. [Электронный ресурс.] Режим доступа: http://100byte.ru/stdntswrks/cshrp/spell/wordCorr.html – (дата обращения: 01.09.2018.)
  2. Русский язык. [Электронный ресурс.] Режим доступа: http://obrazovaka.ru/russkiy-yazyk – (дата обращения: 01.09.2018).
  3. Сайт о русском языке. [Электронный ресурс.] Режим доступа: http://russkiiyazyk.ru – (дата обращения: 01.09.2018).
  4. Учим русский язык. [Электронный ресурс.] Режим доступа: http://tutrus.com – (дата обращения: 01.09.2018).
  5. Окончания существительных. [Электронный ресурс.] Режим доступа: http://www.rusyaz-online.ru/pravila/okonchanija-sush – (дата обращения: 01.09.2018).
  6. Разбор слов по составу. [Электронный ресурс.] Режим доступа: http://morphemeonline.ru/ – (дата обращения: 01.09.2018).
  7. Морфологический словарь русского языка в виде SQL скрипта. [Электронный ресурс.] Режим доступа: https://shra.ru/2017/03/morfologicheskijj-slovar-russkogo-yazyka-v-vide-sql-skripta/ – (дата обращения: 01.09.2018).
  8. Расстояние Левенштейна. [Электронный ресурс.] Режим доступа: https://ru.wikipedia.org/wiki/Расстояние_Левенштейна – (дата обращения: 01.09.2018).
  9. Damerau–Levenshtein distance [Электронный ресурс] – Режим доступа: https://en.wikipedia.org/wiki/Damerau%E2%80%93Levenshtein_distance – (дата обращения: 01.09.2018).
  10. Garbe W. 1000x Faster Spelling Correction algorithm (2012). [Электронный ресурс.] Режим доступа: https://medium.com/@wolfgarbe/1000x-faster-spelling-correction-algorithm-2012-8701fcd87a5f – (дата обращения: 01.09.2018).
  11. Варшавский П. Р., Алехин Р. В. Метод поиска решений в интеллектуальных системах поддержки принятия решений на основе прецедентов. International Journal "Information Models and Analyses" Vol.2 / 2013, Number 4385.

Список работ

Рейтинг@Mail.ru