Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
[01] Соколов В.А. Формальные языки и грамматики....doc
Скачиваний:
97
Добавлен:
29.10.2018
Размер:
1.44 Mб
Скачать

Лекция 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 ... b, то 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 (включая пустую строку).