Раздел 2. Конечные автоматы
Лекция 4.
Тема лекции. Конечные автоматы.
4.1. Конечные автоматы
Конечный автомат представляет собой пятерку
![]()
где, Q - конечное множество состояний автомата,
T - непустое конечное множество входных символов, входной алфавит,
- начальное
состояние,
- непустое множество
заключительных состояний автомата,
t- переходная функция
![]()
Такой автомат
работает как распознаватель следующим
образом (рис.1.11). На ленте записана
входная строка, ограниченная с двух
сторон концевыми маркерами. Управляющее
устройство находится в начальном
состоянии
.
Входная лента последовательно
просматривается слева направо по одному
символу. Допустим, что с помощью
считывающей головки оказались просмотрены
символы
и управляющее устройство находится в
состоянии
.
Символ
допускается, если существует хотя бы
одно состояние
.

Если такого состояния не существует, автомат останавливает свою работу. В общем случае таких состояний может быть несколько, и распознаватель будет недетерминированным, т.е. речь в этом случае будет идти о недетерминированном конечном автомате.
Строка
допускается автоматом, если существует
последовательность состояний
,
такая, что
,
где
и после прочтения последнего символа
строки был встречен концевой маркер.
Предполагается, что начальный маркер
читается в состоянии
.
Этот факт можно записать с помощью
функции перехода следующим образом
.
В этом случае функцию перехода,
соответствующую одному такту работы
распознавателя, можно рассматривать
как частный случай ее общей формы записи
для строки x
содержащей один символ
и состояния
.
Таким образом, функцию t
можно определить рекурсивно
,
если строка
,
где
и
.
Множество всех строк T(A), допускаемых автоматом A, может быть записано в виде
![]()
Если
праволинейная грамматика, то, как
доказано в [4] существует конечный автомат
такой, что
.
Этот автомат строится из грамматики
следующим образом. Множество состояний
можно получить объединением множества
нетерминальных символов и специально
введенного конечного состояния
,
т.е.
.
Соответственно начальное состояние
совпадет с начальным символом грамматики
.
В качестве входного алфавита используется
множество терминальных символов T.
Определим функцию перехода для каждой
продукции грамматики.
,
если существует правило
и
;
,
если существует правило
;
во всех остальных
случаях.
Таким образом, число элементов области определения функции переходов, для которых ее значение не пустое множество, в точности равно числу продукций в грамматике.
Практика показала,
что одним из удобных способов задания
функции переходов является граф
переходов
или его еще называют граф
состояний.
Граф состояний
является направленным графом и строится
следующим образом. Каждому состоянию
множества Q
соответствует одна вершина множества
V.
Все вершины, кроме
заключительных, обозначаются на рисунках
в виде окружностей. На начальную вершину,
соответствующую начальному состоянию
автомата, указывает стрелка. Заключительная
вершина изображается прямоугольником.
Ребро
существует на графе, если для символа
и состояния
значение функции
t(B,a)
не пусто и равно
.
На рис. 1.12 изображен граф состояний
автомата A.
,
где
![]()
![]()
![]()
![]()
![]()
![]()

Граф состояний
автомата, построенного на основе
праволинейной грамматики
,
показан на рис. 1.13. Покажем соответствие
между продукциями грамматики G
и элементами функции перехода автомата.
![]()
![]()
![]()
![]()
![]()
где f - заключительное состояние автомата.

Рассмотрим еще один пример грамматики, порождающей следующие предложения языка
![]()
Продукции этой грамматики имеют вид
![]()
![]()
Построим для этой грамматики конечный автомат. Граф его состояний приведен на рис. 1.14.

По графу видно, что конечный автомат недетерминированный, поскольку из состояния S выходят два ребра с символом a. Функция перехода для символа a в состоянии S имеет два значения.
![]()
Как известно,
недетерминированный автомат достаточно
сложно использовать для разбора. Поэтому
нас интересует возможность преобразования
недетерминированного автомата в
детерминированный. Для конечных автоматов
этот вопрос решается положительно.
Доказано [4], что, если A
- недетерминированный автомат, то
существует детерминированный автомат
A',
такой, что
.
Допустим, что функция переходов
имеет множество значений
.
Будем считать это множество одним новым
состоянием q'.
Присоединим это состояние к множеству
состояний Q
автомата, т.е.
.
Определим функцию перехода для нового
состояния q'.
для всех
![]()
Выполнив данное преобразование для всех функций перехода, имеющих не единственное значение, получим детерминированный автомат. Запишем для приведенного выше примера все функции перехода.
![]()
![]()
![]()
![]()
Введем новое
состояние
и перепишем функции перехода.
![]()
![]()
![]()
так как одно
состояние из
f
- конечное, а
![]()
Граф состояний полученного детерминированного автомата показан на рис. 1.15.

/*------------------------*/
#include <iostream.h>
int sntx(lenta,pread)
int *pread;
char lenta[80];
{ int i;
struct state;
struct rebro{
char t;
state *p;
} sr[2],dfr[1],dr[1];
rebro *vr;
struct state{
int n;
char k;
rebro *r;
} s,df,d;
state * v;
/*----------------------------*/
s.n=2;
s.k='0';
s.r=&sr[0];
sr[0].t='a';
sr[0].p=&df;
sr[1].p=&d;
sr[1].t='b';
df.n=1;
df.k='k';
df.r=&dfr[0];
dfr[0].t='0';
dfr[0].p=&df;
d.n=1;
d.k='0';
d.r=&dr[0];
dr[0].t='0';
dr[0].p=&df;
/*-----------------------------------*/
v = &s;
i = 1;
vr=(*v).r;
while (i<=(*v).n) {
if ((*vr).t == lenta[*pread]) {
(*pread)++;
v=(*vr).p;
vr=(*v).r;
i=1;
}
else {i++;vr++;}
}
if ((lenta[*pread] == 'k') && ((*v).k == 'k'))
return 0;
else
return 1;
}
main()
{
char stroka[80];
int n, sm;
int *psm = &sm;
for (n=1; n<10;
n++)
{
cin >> stroka;
sm = 0;
if (sntx(stroka,psm) == 0)
cout << "all right \n";
else
cout << "error column -> " << sm+1 << "\n";
}
}
