Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
3_Кінцеві автомати_РВ-НКА-ДКА.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
411 Кб
Скачать
☆

3.2. Від регулярного виразу до нка

Є чимало стратегій побудови розпізнавача на основі регулярних виразів; кожна з них має свої переваги й недоліки. Одна зі стратегій, використовувана в багатьох текстових редакторах, полягає в побудові НКА на основі регулярного виразу й наступному моделюванні його поводження із застосуванням алгоритмів 3.3 й 3.4. Є й альтернативні реалізації ДКА по регулярних виразах, у яких НКА явно не будується. Цей розділ завершується обговоренням питань швидкості роботи й розміру пам'яті при реалізації розпізнавачів на основі НКА й ДКА.

3.2.1 Побудова нка по регулярному виразу

Зараз ми розглянемо алгоритм побудови НКА на основі регулярного виразу. Є багато варіацій цього алгоритму, і тут буде представлений найпростіший варіант, легкий у реалізації. Алгоритм синтаксично керований, оскільки використає в процесі побудови синтаксичну структуру регулярного виразу. Розгалуження алгоритму відповідають розгалуженням визначення регулярного виразу. Спочатку покажемо, як будується автомат для розпізнавання ε й будь-якого символу з алфавіту; потім визначимо, як конструюється автомат для виразів, що містять оператори об'єднання, конкатенації або замикання Кліні. Наприклад, для виразу r і s індуктивно побудуємо НКА з автоматів для r і s.

У процесі створення НКА кожен крок вносить не більше двох нових станів. У результаті НКА, побудований по регулярному виразу, має кількість станів, що перевищує число символів й операторів у регулярному виразу не більш ніж у два рази.

Алгоритм 3.3. Побудова НКА на основі регулярного виразу (побудова Томпсона)

Вхід. Регулярний вираз r над алфавітом V.

Вихід. НКА N, що допускає L(r).

Метод. Спочатку ми розбираємо r на складові підвирази. Потім, використовуючи наведені нижче правила (1) і (2), будуємо НКА для кожного базового символу в r (які являють собою символи алфавіту або ε). Базові символи відповідають частинам (1) і (2) у визначенні регулярного виразу. Важливо розуміти, що якщо в регулярному виразі r деякий символ а зустрічається кілька разів, для кожного його входження створюється окремий НКА.

Потім, послідовно з синтаксичною структурою регулярного виразу r, індуктивно комбінуємо ці НКА з використанням правила (3), поки не буде отриманий НКА для всього виразу. Кожен проміжний НКА відповідає своєму підвиразу r і має кілька важливих властивостей: такий автомат має рівно один заключний стан, жодна дуга не входить у початковий стан і жодна не виходить із заключного.

1. Для ε будуємо НКА.

Тут i- новий початковий стан, а f – новий заключний. Очевидно, що цей НКА розпізнає {ε}.

2. Для а є V будуємо НКА

start

Тут також i - новий початковий стан, а f – новий заключний. Цей НКА розпізнає {а}.

3. Нехай N(s) і N(t) являють собою НКА для регулярних виразів s й t.

а) Для регулярного виразу s|t будуємо наступній складений НКА N(s|t):

Тут i— новий початковий стан, а f – новий заключний. Є переходи по ε від i до стартових станів N(s) і N(t) а також переходи по ε із заключних станів N(s) і N(t) у новий заключний стан f. Початкові й заключні стани N(s) і N(t) не збігаються з початковими й заключними станами N(s|t). Помітимо, що будь-який шлях від і до f повинен проходити або тільки через N(s), або тільки через N(t). У відповідності зі сказаним складений НКА розпізнає L(s)\ L(t).

b) Для регулярного виразу st будується складений НКА N(st):

start

Початковий стан N(s) стає початковим станом складеного НКА, а заключний стан N(t)— заключним станом складеного автомата. Заключний стан N(s) зливається з початковим N(t); таким чином, всі переходи з початкового стану N(t) перетворяться в переходи із заключного стану N(s). Новий об'єднаний стан втрачає свій статус початкового/заключного в комбінованому автоматі. Шлях від i до f повинен пройти спочатку через N(s), а потім — через N(t), так що мітки на цьому шляхи являють собою рядок з L(s)L(t). Оскільки немає дуг, які входять у початковий стан N(t) або залишають заключний N(s), не існує шляху від i до f, який би повертався від N(t) до N(s). Отже, складений НКА розпізнає L(s)L(t).

с) Для регулярного виразу s* побудуємо складений НКА N(s*)

Тут i— новий початковий стан, а f – новий заключний. У складеному НКА можемо пройти від i до f або прямо, уздовж дуги ε, що представляє той факт, що ε € (L(s))*, або через N(s) один або більше раз. Очевидно, що складений НКА розпізнає (L(s))* .

d) Для регулярного виразу в дужках (s) у якості НКА використаємо N(s).

Кожен новий стан одержує індивідуальне ім'я. Таким чином, ніякі зі­ станів кожного з компонентів НКА не можуть мати те саме ім'я. Навіть якщо в r кільки разів зустрічається той самий символ, для кожного екземпляра цього символу створюється окремий НКА із власними станами. D

Ми можемо переконатися, що кожен крок побудови в алгоритмі 3.3 дає НКА, що розпізнає коректну мову. Крім того, побудова приводить до НКА N(r) з наступними властивостями.

  1. N(r) має кількість станів, що перевищує кількість символів й операторів у r не більш ніж у два рази. Це випливає з того, що на кожному етапі побудови створюється не більше двох нових станів.

  2. N(r) має рівно один початковий й один заключний стан. Заключний стан не має вихідних переходів. Це властивість вірна й для всіх складових автоматів.

  3. Кожен стан N(r) має або один вихідний перехід для символу з V, або не більше двох вихідних ε-переходів.

Приклад 3.4

Застосуємо алгоритм 3.3 до побудови N(r) для регулярного виразу r = (a|b)*abb. На рис. 3.4 показане дерево розбору для r, аналогічне деревам, створеним для арифметичних виразів у розділі 2.2. Для складової r1, першого а, будуємо НКА

start

Для r2 НКА виглядає як

Тепер можна з'єднати N(r1) й N(r2) з використанням правила об'єднання, одержавши при цьому НКА для r3 = r1|r2

НКА для (r3) той же, що й для r3, а для (r3)* він виглядає в такий спосіб:

НКА для r6 = а являє собою

start

Щоб одержати автомат для r5 r6, потрібно об'єднати стани 7 й 7' у єдиний стан 7. У результаті одержуємо НКА

Продовжуючи роботу, одержимо НКА для r11 = (a|b)*abb, що показаний на рис. 3.5.

Рис. 3.5. Граф переходів НКА для регулярного виразу (a|b)*abb

Як видно, цей граф відрізняється від графа переходів, що був наведений на рис. 3.1, для того ж самого регулярного виразу.

Це говорить про те, що існує не один алгоритм перетворення РВ в НКА.