Опубликован: 26.09.2006 | Доступ: свободный | Студентов: 1772 / 459 | Оценка: 4.25 / 4.12 | Длительность: 17:09:00
ISBN: 978-5-9556-0066-6
Специальности: Программист, Математик
Лекция 13:

Формальные языки

Применение конечных автоматов в программировании

Задача. По заданному регулярному выражению \al над алфавитом A = \{a_1, a_2\dts a_n\} найти в тексте x наименьший префикс, содержащий слово из L(\al).

Решение. Строится регулярное выражение \beta = (a_1 \vee
a_2 \vee \ldots \vee a_n)^\ast \al и для него — недетерминированный конечный автомат с \varepsilon -переходами. Пусть это будет автомат \Re = (Q, A, q_0, F, \varphi). Если при чтении текста x построенным автоматом мы приходим в финальное состояние, то это означает, что мы прочитали префикс текста x, содержащий слово из языка L(\al).

Алгоритм, моделирующий работу недетерминированного конечного автомата \Re с \varepsilon -переходами на входном слове x = x_1 x_2 \ldots x_n \in A^\ast.

\formula{
Q_0:= \{q_0\};\\
\t for\ i := 1\ \t to\ n\ \t do\ Q_i:=
\bigcup_{q\in Q_{i-1}}\varphi (q,x_{i});\\
\t{Пометить все состояния из}\ Q_i\ \t{как рассмотренные};\\
\t{Пометить все состояния из}\ Q \backslash Q_i\ \t{как
нерассмотренные};\\
\t{Все состояния из}\ Q_i\ \t{поместить в очередь};\\
\t While\ \t{Очередь не пуста}\
\t do\\
\mbox{}\qq \{t :=\ \t{головной элемент из очереди (с удалением)};\\
\mbox{}\qq \t For\ u \in \varphi(t,
\varepsilon) \& u\t{ —
не рассмотрен}\ \t do\\
\mbox{}\qq\qq \{\t{Пометить}\ u\ \t{как рассмотренное};\\
\mbox{}\qq\qq \t{Поместить}\ u\ \t{в хвост очереди
и в}\ Q_i\}\}
}

Оценим трудоемкость приведенного алгоритма. Пусть |Q| =
m, |\varphi(q, a)| \le e, тогда тело цикла while оценивается как O(e), а тело цикла " for i := 1 to n do " как O(e\cdot m) и весь алгоритм имеет трудоемкость O(e \cdot m \cdot n).

Анализируя алгоритм построения автомата \Re = (Q, A, q_0,
\{f\}, \varphi) с \varepsilon -переходами по регулярному выражению \beta, легко установить следующие свойства:

  • |Q| < 2\cdot |\beta|, где |\beta| — длина выражения \beta с учетом скобок и символов операций;
  • q_0 \ne f ;
  • (\forall x \in (A \cup \{\varepsilon\})) \varphi(f, x) =
\varnothing ;
  • (\forall q \in Q) \suml_{a\in (A\cup \{\varepsilon\})}
|\varphi (q,x)| \le 2.

Учитывая приведенные свойства, можем теперь оценить алгоритм, моделирующий работу автомата \Re, величиной O(n \cdot
|\beta|).

Рассмотрим теперь задачу, частную по отношению к рассмотренной выше, полагая, что вместо регулярного выражения \al задано одно слово-образец y.

Задача. Требуется найти вхождение заданного слова-образца y = y_1 y_2 \ldots y_n в слово-текст x = x_1 x_2 \ldots x_m или установить, что такого вхождения нет.

Определение. По данному образцу y определим функцию {S_y\colon A^\ast
\!\to\! A^\ast} следующим образом: (\forall x \in A^\ast)S_y(x) — наибольший префикс слова y, являющийся суффиксом слова x.

Очевидно, что (\forall x \in A^\ast)\,|\,S_y(x)| =
\max\{k\,|\,{\rm pref}_k y = {\rm suff}_k x\}.

Утверждение 4. Для любой строки x и любого символа a |S_y(xa)| \le |S_y (x)| +1.

Действительно, предположим, что |S_y(xa)| > |S_y(x)| + 1 и S_y(xa)  = ua, тогда |ua| > |S_y(x)| + 1, а u будет префиксом и суффиксом строки x, причем |u| >
|S_y(x)|, что противоречит определению |S_y(x)|.

Утверждение 5. Пусть q = |S_y(x)|, тогда для любого символа a |S_y(xa)| = |S_y(y_1 y_2 \ldots y_q a)|.

Действительно, по предыдущему утверждению, |S_y(xa)| \le q + 1, поэтому значение |S_y(xa)| не изменится, если от строки xa оставить последние q + 1 символов, а именно y_1 y_2 \ldots y_q a. Построим по слову-образцу y = y_1 y_2 \ldots y_n конечный автомат

\eq*{
\Re = (Q, A, q_0, \{f\}, \varphi),
}
где Q = \{0, 1\dts n\}, q_0 = 0, f = n, а переходную функцию \varphi определим следующим образом:
\eq*{
(\forall q \in Q)(\forall a \in A) \varphi (q, a)
= |S_y (y_1 y_2 \ldots y_q a)|.
}
Для построенного автомата, очевидно, будет справедливо следующее утверждение.

Утверждение 6. Прочитав текст x, автомат \Re = (Q, A, q_0, \{f\},
\varphi) будет находиться в состоянии |S_y(x)|.

Алгоритм вычисления функции переходов:

\formula{
n := {\rm length}(y);\\
\t for\ q:= 0\ \t to\ n\ \t do
for\ a \in A\
\t do\ k := \min\{n + 1,\ q + 2\};\\
\t repeat\ k := k - 1\ \t until\ y_1 y_2\ldots y_q =
{\rm suff}(y_1 y_2 \ldots y_q\ a);\\
\varphi (q, a) := k
}
Время работы этого алгоритма O(n^3 |A|).

Пример. Пусть алфавит A = \{a, b\} и Y = aabbaab. Допустим, что, читая текст x, мы обнаружили некоторый префикс x_1 x_2\ldots x_i слова x, заканчивающийся фрагментом aabbaa, который является префиксом слова Y, а следующий символ x_{i+1} в тексте x не равен b, то есть не совпадает с очередным символом слова Y. Считаем, что потерпели неудачу, но при этом заметим, что суффикс aa этого фрагмента является его префиксом и, возможно, он является префиксом некоторого вхождения слова Y в x.

Делая такое предположение, продолжаем читать x, сравнивая очередные символы слова x с соответствующими, начиная с третьего, символами слова Y в надежде на этот раз обнаружить его вхождение в x.

Таким образом, читая x, будем считать, что мы в каждый момент находимся в некотором состоянии j, если только что прочитан префикс Y' слова Y длины j. Если при чтении следующего символа мы терпим неудачу, то переходим в новое состояние j', такое, что j' — максимальный префикс слова Y', являющийся его суффиксом. Функцию, которая состоянию j ставит в соответствие j', называют функцией откатов. В нашем примере ее можно изобразить следующей диаграммой.


Рис. 13.3.
Антон Сиротинкин
Антон Сиротинкин

на стр 6, лекции 3, Очевидно "Ck <= модуль(Gk(е))*b(k+1)" (1) - , подскажите что значит "модуль" и почему это очевидно...