Изменения
Нет описания правки
===Псевдокод===
*<tex>\mathtt{Q}</tex> {{---}} множество состояний ДКА.,*<tex>\mathtt{F}</tex> {{---}} множество терминальных состояний.,*<tex>\mathtt{\delta}</tex> {{---}} функция перехода (<tex>\delta (r,\ a)</tex> {{---}} состояние, в которое можно совершить переход из <tex>r</tex> по символу <tex>a</tex>),*<tex>\mathtt{S}</tex> {{---}} очередь пар <tex>\langle C,\ a \rangle</tex>.,*<tex>\mathtt{P}</tex> {{---}} разбиение множества состояний ДКА.,*<tex>\mathtt{R}</tex> {{---}} класс состояний ДКА.
<tex>\mathtt{findEquivalenceClasses}(Q,\ F,\ \delta)</tex>:
<tex>\mathtt{pushSetsToQueue}(S,\ R_1,\ R_2,\ c)</tex> {{---}} функция, которая добавляет одну из пар <tex>\langle R_1, c \rangle</tex>, <tex>\langle R_2, c \rangle</tex> в очередь S.
*<tex>\mathtt{Q}</tex> {{---}} множество состояний ДКА.,*<tex>\mathtt{F}</tex> {{---}} множество терминальных состояний.,*<tex>\mathtt{\delta}</tex> {{---}} функция перехода (<tex>\delta (r,\ a)</tex> - состояние, в которое можно совершить переход из <tex>r</tex> по символу <tex>a</tex>),*<tex>\mathtt{S}</tex> {{---}} очередь пар <tex>\langle C,\ a \rangle</tex>.,*<tex>\mathtt{P}</tex> {{---}} разбиение множества состояний ДКА.,*<tex>\mathtt{R}</tex> {{---}} класс состояний ДКА.
<tex>\mathtt{findEquivalenceClasses}(Q,\ F,\ \delta)</tex>:
Классы разбиения <tex>P</tex> будем поддерживать с помощью множеств на [[Хеш-таблица | хэш-таблицах]] (само же разбиение - обычный вектор, индекс - номер класса). Это позволит нам эффективно переносить состояния из одного класса в другой (за O(1)).
*<tex>\mathtt{Class}[r]</tex> {{---}} номер класса, которому принадлежит состояние <tex>r</tex>,*<tex>\mathtt{Queue}</tex> {{---}} очередь пар <tex>\langle C,\ a \rangle</tex>, где <tex>C</tex> {{---}} номер класса (сплиттера),*<tex>\mathtt{InQueue}</tex> {{---}} двумерный массив булеанов, <tex>\mathtt{InQueue}[C][a] == </tex> ''true'', если <tex>\langle C,\ a \rangle</tex> находится в очереди <tex>\mathtt{Queue}</tex>,*<tex>\mathtt{Inv}[r][a]</tex> {{---}} массив состояний, из которых есть ребра по символу <tex>a</tex> в состояние <tex>r</tex> (мы не меняем исходный автомат, потому может быть построен раз перед началом работы алгоритма),
Для обработки <tex>T'</tex> за <tex>O(|Q| + |\mathtt{Inverse}|)</tex> нам понадобится следующая структура:
*<tex>\mathtt{Involved}</tex> {{---}} список из номеров классов, содержащихся во множестве <tex>T'</tex>;,*<tex>\mathtt{Count}</tex> {{---}} целочисленный массив, где <tex>\mathtt{Count}[i]</tex> хранит количество состояний из класса <tex>i</tex>, которые содержатся в <tex>\mathtt{Inverse}</tex>;,*<tex>\mathtt{Twin}</tex> {{---}} массив, хранящий в <tex>\mathtt{Twin}[i]</tex> номер нового класса, образовавшегося при разбиении класса <tex>i</tex>.
<tex>\mathtt{findEquivalenceClasses}(Q,\ F,\ \delta)</tex>:
Вообще, алгоритм можно реализовать и с меньшим количеством используемых структур (что делает код на порядок читабельнее).
Заметим, что вообще нам не важен порядок доставания элементов из "очереди", потому вместо очереди <tex>\mathtt{Queue}</tex> и массива <tex>\mathtt{InQueue}</tex> можно обойтись одним множеством одной хэш-таблицей, содержащей множество пар (оставим название <tex>\mathtt{Queue}</tex>). Притом операции изъятия и добавления в хэ-таблицу производятся за <tex>O(1)</tex>, потому ассимптотика не ухудшится.
Все классы разбиения будем по-прежнему хранить в векторе хэш-сетов <tex>\mathtt{P}</tex>. *<tex>\mathtt{Class}[r]</tex> {{---}} номер индекс классав <tex>\mathtt{P}</tex>, которому принадлежит состояние <tex>r</tex>,*<tex>\mathtt{Queue}</tex> {{---}} множество пар <tex>\langle C,\ a \rangle</tex>,*<tex>\mathtt{Inv}[r][a]</tex> {{---}} массив состояний, из которых есть ребра по символу <tex>a</tex> в состояние <tex>r</tex> (мы не меняем исходный автомат, потому может быть построен раз перед началом работы алгоритма),*<tex>\mathtt{Involved}</tex> {{---}} хэш-таблица ассоциативный массив из номеров классов в векторы из номеров вершин.
<tex>\mathtt{findEquivalenceClasses}(Q,\ F,\ \delta)</tex>: