Список работ

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

Содержание

Введение

Приводятся описание таблиц базы данных (БД), встроенной в систему автоматической правки русского текста. Также приводятся программы формирования, заполнения и редактирования таблиц БД.
Работа с таблицами ведется в среде 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];
        }

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

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

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

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

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

Таблица новых слов, а они так же вставляются и в all_words_dist, используется для пополнения таблицы слов-соседей. Оно выполняется после проверки новых слов: если в neighbors попало слово с ошибкой, то оно будет удалено и из neighbors, и из all_words_dist.
Проверка выполняется человеком, хорошо владеющим русским языком.
При правке текста приложение обращается к таблицам в 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;

namespace WindowsFormsApplicationWordsWithoutLetter
{
    public partial class FormTextAnalysis : Form
    {
        int added, updated, newWords;
        string fl = ""; // Файл с разбираемым текстом
        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;
        SqlCommand cmdWord, cmdWordAdd, cmdNeighbor, cmdNeighborAdd, cmdNeighborUpdate, cmdNewWordAdd, cmdWordDel, cmdWordCode,
                cmdLeftContext, cmdRightContext;
        SqlConnection conWord, conWordAdd, conNeighbor, conNeighborAdd, conNeighborUpdate, conNewWordAdd, conWordDel, conWordCode,
            conLeftContext, conRightContext;
        int minWordLen = 3; // Если длина слова меньше minWordLen, то оно не проверяется, а для замены выставляется с высоким показателем (равен 100)
        int maxCost = -5; // Максимально допустимая цена замены с отрицательным знаком
        //
        public FormTextAnalysis()
        {
            InitializeComponent();
            //
            textBoxCheck.Text = "Старик пасмотрел на карову сваю:" + Environment.NewLine
                    + "– Зачем я, Бурёнка, тебя прадаю?" + Environment.NewLine
                    + "Карову сваю не прадам никому –" + Environment.NewLine
                    + "Такая скатина нужна самому!";
            //textBoxCheck.Text = "я любопытно смотрю на высокую деревянную колокольню или старую темную церковь";
            //
            // Максимально допустимая цена замены с отрицательным знаком
            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;
            cmdWordDel.CommandText = "select 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);
            //
        }
        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 string checkWords_1(string words) // Первый проход правки текста
        {
            int code0, wordIndex, i, cnt, cnt2, levDist, candidateCode, leftNeigh, rightNeigh;
            string word0, word, wordDel, candidate;
            List<Candidate> allCandidates = new List<Candidate>();
            bool isUpper;
            //
            MessageBox.Show(words);
            arrWords = words.Split(' ').ToArray();
            cnt = arrWords.Count();
            words = "";
            for (wordIndex = 0; wordIndex < cnt; wordIndex++)
            {
                allCandidates.Clear();
                word0 = arrWords[wordIndex];
                word = word0.ToLower();
                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
                {
                    // Поиск в word_del
                    for (i = 0; i < word.Length; i++)
                    {
                        wordDel = word.Substring(0, i) + word.Substring(i + 1); // word без одной буквы
                        // Ищем прежде укороченное слово в all_words_dist
                        //cmdWord.Parameters["@word"].Value = wordDel;
                        //conWord.Open();
                        //readerWord = cmdWord.ExecuteReader();
                        //if (readerWord.Read())
                        //{
                        //    candidateCode = readerWord.GetInt32(0);
                        //    candidate = isUpper ? wordDel.ToUpper().Substring(0, 1) + wordDel.Substring(1) : wordDel;
                        //    allCandidates.Add(new Candidate() { CandidateName = candidate, CandidateCode = candidateCode });
                        //}
                        //conWord.Close();
                        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();
                    }
                    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);
                                // Число соседств с предшествующим словом
                                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;
                            }
                            //Console.WriteLine("\nДо сортировки:");
                            //foreach (Candidate cand in allCandidates) Console.WriteLine(cand.CandidateName + " - " + cand.CandidateFactor);
                            allCandidates.Sort(); // Сортировка по убыванию показателя CandidateFactor
                            //Console.WriteLine("\nПосле сортировки:");
                            //foreach (Candidate cand in allCandidates) Console.WriteLine(cand.CandidateName + " - " + cand.CandidateFactor);
                            word0 = allCandidates[0].CandidateName;
                            word0 = word0.Substring(word0.IndexOf(" ") + 1);
                        }
                    }
                }
                arrWords[wordIndex] = word0.ToLower();
                words += word0 + (wordIndex < cnt - 1 ? " " : "");
            }
            return words;
        }
        private string checkWords_2(string words) // Второй проход правки текста
        {
            int wordIndex, wordIndex2, cnt, cnt2, cnt2_1, code0, code02 = 0;
            string words2, word0, word, word2 = "";
            string[] arrWords2;
            bool isUpper, replaceWord0;
            List<Candidate> allCandidates = new List<Candidate>();
            List<Context> allCandidatesRight = new List<Context>();
            List<Context> allCandidatesLeft = new List<Context>();
            //
            List<Candidate> allCandidatesR0 = new List<Candidate>(); // Для правого контекста текущего слова
            List<Context> allCandidatesRight0 = new List<Context>();
            //
            words2 = shrinkWords(words);
            MessageBox.Show(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();
                    isUpper = word0[0] != word[0];
                    replaceWord0 = true;
                    allCandidates.Clear();
                    allCandidatesRight.Clear();
                    allCandidatesLeft.Clear();
                    //
                    // Поиск в all_words_dist
                    cmdWord.Parameters["@word"].Value = word;
                    conWord.Open();
                    readerWord = cmdWord.ExecuteReader();
                    code0 = readerWord.Read() ? readerWord.GetInt32(0) : -1;
                    conWord.Close();
                    if (wordIndex2 > 0) fillInAllCandidates(allCandidatesRight, arrWords2[wordIndex2 - 1], true); // Правый контекст слова arrWords2[wordIndex2 - 1]
                    if (wordIndex2 < cnt2_1)
                    {
                        word2 = arrWords2[wordIndex2 + 1];
                        code02 = fillInAllCandidates(allCandidatesLeft, word2, false); // Левый контекст слова arrWords2[wordIndex2 + 1]
                    }
                    //
                    //Console.WriteLine("\nСлово найдено в all_words_dist. Проверяемое слово: " + word0);
                    //if (wordIndex > 0) Console.WriteLine("\nПредшествующее слово : " + arrWords2[wordIndex2 - 1]);
                    //if (wordIndex < cnt - 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(contR.CandidateCode + " - " + contR.CandidateFactor);
                        //Console.WriteLine("\nЛевый контекст последующего слова: " + arrWords2[wordIndex2 + 1]);
                        //foreach (Context contL in allCandidatesLeft) Console.WriteLine(contL.CandidateCode + " - " + contL.CandidateFactor);
                        //
                        // Оставляем слово, если оно есть в обоих контекстах
                        if (!allCandidatesLeft.Exists(x => x.CandidateCode == code0) || !allCandidatesRight.Exists(x => x.CandidateCode == code0))
                        //
                        // Оставляем слово, если оно есть в правом контексте предшествующего слова
                        //if (!allCandidatesRight.Exists(x => x.CandidateCode == code0))
                        {
                            // Добавляем в список кандидатов только те слова, которые есть в обоих контекстах
                            foreach (Context contR in allCandidatesRight)
                            {
                                int codeR = contR.CandidateCode;
                                if (allCandidatesLeft.Exists(x => x.CandidateCode == codeR))
                                {
                                    Context contL = allCandidatesLeft.Find(x => x.CandidateCode == codeR);
                                    allCandidates.Add(new Candidate()
                                    {
                                        CandidateCode = codeR,
                                        CandidateFactor = findCandidateFactor(word, contR.CandidateCode, contR.CandidateFactor + contL.CandidateFactor, true)
                                    });
                                }
                            }
                            if (allCandidates.Count > 0)
                            {
                                // Заменяем слово, если оно есть в правом контексте предшествующего слова, а цена замены меньше допустимой величины
                                if (allCandidatesRight.Exists(x => x.CandidateCode == code0))
                                {
                                    allCandidates.Sort();
                                    replaceWord0 = allCandidates[0].CandidateFactor > maxCost; // Знак '>', поскольку обе величины < 0
                                    //Console.WriteLine("\nОставляем слово: " + word0);
                                    //Console.WriteLine("\nПоказатель: " + allCandidates[0].CandidateFactor + Environment.NewLine);
                                }
                                // Ищем слово в его объединенном контексте
                                //Console.WriteLine("\nОбъединенный контекст слова: " + word0);
                                //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)
                                allCandidates.Add(new Candidate()
                                {
                                    CandidateCode = contR.CandidateCode,
                                    CandidateFactor = findCandidateFactor(word, contR.CandidateCode, contR.CandidateFactor, true)
                                });
                        //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)
                                });
                            if (wordIndex2 < cnt2_1) // Находим правый контекст текущего слова
                            {
                                allCandidatesRight0.Clear();
                                fillInAllCandidates(allCandidatesRight0, word, true); // Правый контекст текущего слова word0 = arrWords2[wordIndex2]
                                // Проверяем, есть ли слово word2 в правом контексте текущего слова word0
                                if (!allCandidatesRight0.Exists(x => x.CandidateCode == code02)) // Слова word2 нет в правом контексте текущего слова word0. Ищем ему замену
                                {
                                    allCandidatesR0.Clear(); // Правый контекст текущего слова
                                    foreach (Context contR0 in allCandidatesRight0)
                                        allCandidatesR0.Add(new Candidate()
                                        {
                                            CandidateCode = contR0.CandidateCode,
                                            CandidateFactor = findCandidateFactor(word2, 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);
                                    }
                                }
                            }
                        }
                    }
                    //else
                    //    Console.WriteLine("\nПоиск в левом контексте. Оставили слово " + word0);
                    if (allCandidates.Count > 0 && replaceWord0)
                    {
                        allCandidates.Sort(); // Сортировка по убыванию показателя CandidateFactor
                        // Заменяем, если цена замены меньше допустимой величины
                        if (allCandidates[0].CandidateFactor > maxCost) // Знак '>', поскольку обе величины < 0
                        {
                            // Находим слово по его коду
                            cmdWordCode.Parameters["@code"].Value = allCandidates[0].CandidateCode;
                            conWordCode.Open();
                            readerWordCode = cmdWordCode.ExecuteReader();
                            readerWordCode.Read();
                            word0 = readerWordCode.GetString(0).Trim();
                            word0 = isUpper ? word0.ToUpper().Substring(0, 1) + word0.Substring(1) : word0;
                            conWordCode.Close();
                        }
                    }
                    arrWords2[wordIndex2] = word0.ToLower();
                }
                words += word0 + (wordIndex < cnt - 1 ? " " : "");
            }
            return words;
        }
        private int findCandidateFactor(string word, int code, int factor, bool Levenshtein)
        {
            if (Levenshtein)
            {
                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(word, candidate);
                //Console.WriteLine("\nСлово " + word);
                //Console.WriteLine("\nКандидат " + candidate);
                //Console.WriteLine("\nПоказатель " + candidateFactor);
                return -candidateFactor; // Ставим "-", поскольку перед выбором кандидатов сортируем по убыванию 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)
            {
                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
            {
                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 text, line, words = "", textChecked = "", c;
            List<int> punct = new List<int>();
            if (textBoxCheck.Text.Trim().Length == 0)
            {
                if (fl.Length == 0)
                    MessageBox.Show("Не выбран файл");
                else // Заполняем текстовое из файла
                {
                    sR = new StreamReader(fl, Encoding.UTF8);
                    while (!sR.EndOfStream) textBoxCheck.Text += (sR.ReadLine() + Environment.NewLine);
                    sR.Close();
                }
            }
            if (textBoxCheck.Text.Trim().Length == 0)
            {
                MessageBox.Show("Пусто");
                return;
            }
            //
            // Первый проход
            text = textBoxCheck.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(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_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;
            //
            // Второй проход
            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;
            }
            //
            textBoxAfterCheck.Text = textChecked;
            MessageBox.Show("Готово");
        }
        private void buttonClear_Click(object sender, EventArgs e)
        {
            textBoxCheck.Text = "";
            textBoxAfterCheck.Text = "";
        }
        // В результате вычислений в 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];
        }
        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;
        }
    }
    public class Candidate : IComparable<Candidate>
    {
        public string CandidateName { get; set; }
        public int CandidateCode { get; set; }
        public int CandidateFactor { 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. Словообразовательный суффикс:
  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. Обозначаем части слова с помощью графических обозначений.

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

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

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

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

Приложения

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

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

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]

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

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)

Запросы

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

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 = '..ыба'

Удаление записей из таблиц правки текста

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

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

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

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

-- 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)

Сжатие базы данных

USE [dbname];
GO
-- Изменяем модель восстановления данных на SIMPLE
ALTER DATABASE [dbname]
SET RECOVERY SIMPLE;
GO
-- Сжимаем log-файл до 1 MB
DBCC SHRINKFILE ([dbname_Log], 1);
GO
-- Устанавливаем FULL-модель восстановления данных (создает огромный log-файл)
ALTER DATABASE [dbname]
SET RECOVERY FULL;
GO

Выбор и удаление повторяющихся слов таблицы 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).

Список работ

Рейтинг@Mail.ru