- •Курс лекций
- •Оглавление
- •Лекция 1 Языки и грамматики Языки
- •ГГрамматики
- •Лекция 2 Конечные автоматы Автоматы
- •Детерминированные конечные автоматы (распознаватели)
- •Языки и детерминированные конечные автоматы
- •Лекция 3 Конечные автоматы Недетерминированные конечные автоматы (распознаватели)
- •Эквивалентность дка и нка
- •Лекция 4 Конечные автоматы Минимизация конечных автоматов
- •Лекция 5 Регулярные выражения и регулярные грамматики
- •Регулярные выражения
- •Связь между регулярными выражениями и автоматными языками
- •Лекция 6 Регулярные выражения и регулярные грамматики Регулярные грамматики
- •Лекция 7 Свойства регулярных языков
- •Замкнутость класса регулярных языков
- •Алгоритмические проблемы регулярных языков
- •Лемма о расширении регулярных языков
- •Лекция 8 Контекстно-свободные языки
- •Контекстно-свободные грамматики
- •Лекция 9 Контекстно-свободные языки
- •Грамматический разбор
- •Неоднозначность грамматик и языков
- •Лекция 10 Преобразования кс‑грамматик и нормальные формы
- •Методы преобразования грамматик
- •Лекция 11 Преобразования кс‑грамматик и нормальные формы
- •Нормальные формы кс-грамматик
- •Лекция 12 Магазинные автоматы Магазинные автоматы
- •Недетерминированные магазинные автоматы
- •Лекция 13 Магазинные автоматы Магазинные автоматы и кс-языки
- •Лекция 14 Магазинные автоматы Детерминированные магазинные автоматы и детерминированные кс-языки
- •Лекция 15 Свойства контекстно-свободных языков
- •Лемма о расширении
- •Свойства замкнутости класса контекстно-свободных языков
- •Лекция 16 Свойства контекстно-свободных языков Некоторые алгоритмические проблемы для кс-языков
- •Предметный указатель
- •Формальные языки и грамматики Курс лекций
Лекция 1 Языки и грамматики Языки
любой язык основан на использовании определенного алфа-вита. Алфавит – это конечное непустое множество символов S = {a1, a2, a3, ... , an}, n > 0. Строка – упорядоченная конечная последовательность символов алфавита S. Для обозначения строк будем использовать строчные буквы греческого алфавита a, b, g, ... Например, a = aabb означает, что строка, обозначаемая буквой a, представляет собой последовательность из четырех символов aabb.
Конкатенация двух строк a и b – это бинарная операция, ре-зультат которой есть строка ab, полученная приписыванием к стро-ке a справа строки b, т.е. если a = a1 a2 a3 ... an , b = b1 b2 b3 ... bm , то ab = a1 a2 a3 ... an b1 b2 b3 ... bm .
Очевидно, что конкатенация является ассоциативной, но не-коммутативной операцией, т.е. для любых строк a, b, g в алфавите S справедливо равенство a(bg) = (ab)g, но неверно, что для любых a, b ab = ba. Например, если a = ab, b = ba, то ab = abba, а ba = baab, т.е. ab ¹ ba.
Операция обращения строки a обозначается a-1 и дает строку, полученную из a выписыванием всех входящих в нее символов в обратном порядке, т.е. если a = a1 a2 a3 ... an , то a-1 = an an -1 ... a2 a1 . Нетрудно видеть, что для любых строк a и b верно соотношение (ab)-1 = b-1a-1.
Длина строки a обозначается |a| и равна числу символов (с учетом повторений) в этой строке. Так, если a = a1a2a3 ... an, то |a| = n, n ³ 0.
Пустой строкой называется строка e, для которой |e| = 0. Очевидно, что для любой строки a ea = ae = a, т.е. строка e является нейтральным элементом относительно конкатенации. В разных ситуациях бывает необходимо рассматривать структуру строки a, т.е. выделять в ней отдельные части, которые сами являются строками. Пусть
a = bgd, где |b| ³ 0, |g| ³ 0, |d| ³ 0.
Тогда строка b называется префиксом строки a, строка d – ее суффиксом, а g – ее подстрокой. Отсюда, в частности, следует, что пустая подстрока e является подстрокой любой строки a.
Длина строки связана с операцией конкатенации простым соотношением: |ab| = |a| + |b|.
Введем полезное обозначение для результата конкатенации строки a с самой собой: aa = a2, aaa = a3 и т.д.
В общем виде эту операцию над строкой a можно определить рекурсивно: a0 = e, an+1 = ana, n ³ 0. В частности, если a = aa ... a и |a| = n, то a = аn.
Теперь введем одно из основных понятий информатики – понятие формального языка. Формальным языком называется любое множество строк (в данном алфавите S).
Пример 1.1.
Пусть S = {a, b}. Тогда множество L = {a, b, aa, bb, ab, aab} является (конечным) формальным языком в алфавите S.
В дальнейшем в этом курсе лекций слово «язык» будет обозначать формальный язык в некотором заранее фиксированном алфавите.
Пример 1.2.
Множество L = {anbn| n ³ 0} является (бесконечным) языком в алфавите S = {a, b}. Его элементами являются строки вида ab, aabb, aaabbb, ... , в том числе пустая строка e.
Заметим, что не следует путать пустой язык L = Æ, не содержащий ни одной строки, и язык L = {e}, состоящий из единственной (пустой) строки e.
Язык, состоящий из всех строк в алфавите S, обозначается S*. Если L – язык в алфавите S, то, очевидно, L Í S*.
Так как языки – это множества (строк), то над ними можно совершать обычные теоретико-множественные операции объеди-нения È, пересечения Ç, разности \ и образования дополнения (по отношению к S*), т.е. если L – язык в алфавите S, то его дополнение есть множество = S* \ L.
Наряду с этими операциями над языками можно определить еще ряд специфических операций. Пусть L1, L2 – языки в алфавите S, тогда их сцепление – это язык
L1L2 = {ab | a Î L1, b Î L2},
состоящий из всевозможных конкатенаций строк a языка L1 и строк b языка L2, образованных в указанном порядке.
Нетрудно заметить, что операция сцепления двух языков ассо-циативна, но не коммутативна, т.е. для любых языков L1, L2, L3 из S*
(L1L2)L3 = L1(L2L3),
но существует пара языков L1, L2 такая, что L1L2 ¹ L2L1.
Определим еще одну операцию – итерацию языка L:
L0 = {e}, L1 = L, L2 = LL, L3 = LLL, ...
В общем виде операцию Ln (n ³ 0) можно определить рекурсивно следующим образом: L0 = {e}, Ln+1 = LnL, n ³ 0.
Пример 1.3.
Если L = {anbn | n ³ 0}, то L2 = {anbnambm| n ³ 0, m ³ 0}.
Полезно отметить, что если итерировать алфавит S, который сам, в свою очередь, является (конечным) языком, все строки которого имеют длину 1, то последовательно будем иметь:
S0 = {e} = {a | a Î S* & |a| = 0},
S1 = S = {a | a Î S* & |a| = 1},
S2 = {a1a2 | a1 Î S, a2 Î S} = {a | a Î S* & |a| = 2},
и т.д.
В общем случае, Sn = {a | a Î S* и |a| = n}, n ³ 0, т.е. Sn – это множество всех строк длины n в алфавите S.
В заключение этого раздела введем еще одну очень важную операцию над языками – так называемое замыкание Клини (или звездочка), которая определяется следующим образом. Пусть L – произвольный язык, тогда
L* = L0 È L1 È L2 È ... = Li.
Для удобства, чтобы отделить пустую строку e, которая всегда принадлежит L*, иногда используется позитивное замыкание языка L, обозначаемое L+:
L+ = Li = L1 È L2 È ... .
Из определения следует, что L* = {e} È L+.
Заметим, что ранее введенное обозначение языка S* вполне согласуется с только что введенной операцией замыкания: объединение S0 È S1 È S2 È ... как раз и представляет собой множество всех строк в алфавите S (включая пустую строку).