Научная статья на тему 'Одновременный поиск нескольких двоичных шаблонов в потоке с помощью конечного автомата'

Одновременный поиск нескольких двоичных шаблонов в потоке с помощью конечного автомата Текст научной статьи по специальности «Математика»

CC BY
408
44
i Надоели баннеры? Вы всегда можете отключить рекламу.
Область наук
Ключевые слова
ПОИСК БИТОВЫХ ПОСЛЕДОВАТЕЛЬНОСТЕЙ / СИНХРОПОСЫЛКА / ПОИСК ПОДСТРОКИ / КМП-ПОИСК / АЛГОРИТМ АХО КОРАСИК

Аннотация научной статьи по математике, автор научной работы — Панкратов Иван Владимирович

Рассматривается задача поиска булевых векторов в потоке данных. Предлагается метод построения конечного автомата, который ищет одновременно несколько векторов, совершая только две простые операции на каждый бит или группу битов, например байт данных. При этом с увеличением количества искомых шаблонов объём требуемой памяти растёт медленнее, чем суммарная длина шаблонов, а трудоёмкость не изменяется совсем. Приводятся оценки размеров таблиц переходов и выходов автомата. Рассматриваются известные подходы к решению этой задачи. Есть возможность обобщить алгоритм построения поискового автомата на поиск не полностью определённых булевых векторов, однако в этом случае объём требуемой памяти может превышать найденную в данной работе оценку.

i Надоели баннеры? Вы всегда можете отключить рекламу.
iНе можете найти то, что вам нужно? Попробуйте сервис подбора литературы.
i Надоели баннеры? Вы всегда можете отключить рекламу.

Текст научной работы на тему «Одновременный поиск нескольких двоичных шаблонов в потоке с помощью конечного автомата»

2014 Вычислительные методы в дискретной математике №2(24)

ВЫЧИСЛИТЕЛЬНЫЕ МЕТОДЫ В ДИСКРЕТНОЙ МАТЕМАТИКЕ

УДК 519.7

ОДНОВРЕМЕННЫЙ ПОИСК НЕСКОЛЬКИХ ДВОИЧНЫХ ШАБЛОНОВ В ПОТОКЕ С ПОМОЩЬЮ КОНЕЧНОГО АВТОМАТА

И. В. Панкратов

г. Томск, Россия

E-mail: ivan.pankratov2010@yandex.ru

Рассматривается задача поиска булевых векторов в потоке данных. Предлагается метод построения конечного автомата, который ищет одновременно несколько векторов, совершая только две простые операции на каждый бит или группу битов, например байт данных. При этом с увеличением количества искомых шаблонов объём требуемой памяти растёт медленнее, чем суммарная длина шаблонов, а трудоёмкость не изменяется совсем. Приводятся оценки размеров таблиц переходов и выходов автомата. Рассматриваются известные подходы к решению этой задачи. Есть возможность обобщить алгоритм построения поискового автомата на поиск не полностью определённых булевых векторов, однако в этом случае объём требуемой памяти может превышать найденную в данной работе оценку.

Ключевые слова: поиск битовых последовательностей, синхропосылка, поиск подстроки, КМП-поиск, алгоритм Ахо — Корасик.

Введение

Рассматриваемую задачу можно сформулировать так: имеем двоичную последовательность (поток данных) и набор из n булевых векторов (шаблонов) Vi, V2, ..., Vn длин k1, k2, ..., kn соответственно. Необходимо найти вхождения всех шаблонов в последовательность.

Поиск заданных слов в потоке данных применяется в различных анализаторах трафика, для нахождения синхропосылки в шифртексте и в системах беспроводной цифровой связи.

1. Известные подходы к задаче

Рассмотрим стандартные подходы к этой задаче. Оценивать их эффективность будем в предположении, что значения битов в потоке равновероятны и независимы друг от друга.

Можно «прикладывать» шаблоны, начиная с каждого бита потока, и побитно сравнивать их с содержимым потока. Оценим количество сравнений для одного шаблона длиной k битов. Первый бит шаблона нужно сравнивать с битом потока каждый раз, второй — только если первый бит совпал, то есть в среднем в половине случаев, и так

далее. Всего потребуется 1 + — + - + ... + =2 — « 2 сравнения на каждый

бит потока. Если всего шаблонов n, то на каждый бит потока в среднем потребуется 2n сравнений.

Другой подход основан на регистре сдвига, в который последовательно подаются биты из потока. После подачи каждого бита содержимое регистра сравнивается со всеми шаблонами. Тут потребуется ровно п сравнений, но уже не битовых, а целочисленных, если содержимое регистра помещается в элементарный тип данных. С точки зрения реализации тут есть преимущество: сравнивать значение регистра с шаблоном проще и быстрее, чем значения отдельных битов. С другой стороны, если длина регистра отлична от длины шаблона, нужно обнулять старшие биты регистра перед сравнением, что занимает какое-то время, особенно если искомые шаблоны имеют различные длины. Если же регистр не помещается в элементарный тип данных, эта схема затрудняется ещё сильней.

2. Поиск шаблона с помощью конечного автомата

В данной работе предлагается строить конечный автомат [1], на вход которого подаются биты или байты потока, а на выходе получается информация о найденных в потоке шаблонах. На каждый бит или байт потока автомат совершает две простейших операции: изменение состояния по таблице переходов и определение выхода по таблице выходов. При этом автомат осуществляет одновременный поиск произвольного количества шаблонов любой длины, в том числе различной.

К недостаткам такого подхода относится необходимость хранить таблицы переходов и выходов автомата, которые могут оказаться довольно объёмными. Кроме того, при использовании автомата сложно реализовать «мягкий» поиск, допускающий некоторое количество ошибок в потоке.

2.1. Поисковый автомат с битовым входом

Сначала определим автомат с битовым входом, или битовый автомат.

Входной алфавит автомата — {0,1}.

Выходной алфавит должен позволять выдавать информацию о позициях и номерах найденных шаблонов, однако для битового автомата достаточно указать лишь номера найденных шаблонов, поскольку за один такт работы автомата каждый шаблон может быть найден лишь один раз и может заканчиваться только в позиции последнего обработанного бита. Следовательно, выходной алфавит можно задать, например, множеством булевых векторов {0,1}п, где каждому биту сопоставлен взаимно однозначно некоторый шаблон из заданного набора, и бит принимает значение 1, если в текущей позиции закончился этот шаблон.

Определим множество состояний. Если автомат ищет один шаблон, то всё, что ему нужно знать, — это информацию о позициях, в которых этот шаблон мог начаться. Если длина шаблона к битов, а на вход автомата подали г-й бит, где г ^ к, то нас уже не интересует, мог ли шаблон начаться в (г — к)-м бите или ранее, так как если шаблон начался в (г — к)-м бите, то он закончился в (г — 1)-м, и автомат уже выдал информацию о его нахождении. Таким образом, нужно знать, могло ли вхождение шаблона начаться в позициях с номерами г — к + 1, ..., г — 1.

Вместо запоминания позиций возможного начала шаблона в потоке можно хранить длины уже найденных префиксов шаблона. Соответствие между длинами префиксов и позициями такое: шаблон мог начаться в позиции (г — /), если и только если найден его префикс длины / после обработки (г — 1)-го бита. Нас интересуют только длины префиксов от 1 до (к — 1). Состояние такого автомата можно задать булевым вектором длины (к — 1). Состояние автомата для поиска нескольких шаблонов можно задать набором аналогичных векторов.

Однако такой способ задания состояний избыточен, поскольку некоторые значения векторов бессмысленны. Например, для шаблона 101 невозможно найти одновременно префиксы длины 1 и 2 бита, следовательно, векторы, имеющие единицы в соответствующих позициях, задают невозможные состояния. Возможные состояния автомата можно закодировать целыми числами.

2.2. П о с т р о е н и е б и т о в о г о а в т о м а т а

Опишем алгоритм построения битового автомата.

Строится автомат по индукции. Сначала вводится нулевое состояние, соответствующее ситуации, когда не найден ни один префикс ни одного шаблона. Это состояние естественно для начала входной последовательности. Затем алгоритм поочерёдно обрабатывает все состояния условной подачей на вход автомата 0 и 1, попутно сохраняя новые полученные состояния и строя таблицы переходов и выходов автомата. Обработав таким образом все состояния автомата, получим таблицы переходов и выходов, а также таблицу соответствия номеров состояний их описаниям: состоянию в сопоставляется набор Т8 = (Т8,ьТ8,2,...,Т8,п), где Т8^- содержит множество длин найденных префиксов шаблона номер 7.

Обозначим /-й бит вектора V через V [/], биты нумеруем с нуля.

Выходной алфавит автомата — множество булевых векторов длины п. В выходном векторе Г бит Г [7 — 1] соответствует ]-му шаблону.

Алгоритм построения битового поискового автомата

Вход: набор булевых векторов (шаблонов) VI, ^, ... , Vn, их длины к1, к2, ..., кп Выход: функции переходов ф и выходов ^ поискового автомата

1. Запоминаем начальное состояние Т0 := (0, 0,... 0), в := 0.

2. Обрабатываем состояние в условной подачей нуля и единицы. Подаваемый бит обозначим Ь. Сначала зададим Ь := 0.

3. Строим новое состояние Т, в которое автомат должен перейти после подачи бита Ь в состоянии Т8, и соответствующий выходной символ — вектор Г; сначала полагаем Г := 00 ... 0 = 0п.

Для каждого 7 от 1 до п:

3.1. Зададим А := Т8^- и {0}, B^ := 0.

3.2. Для всех / € А если Ь = Vj[/], то Вj := Bj и {/ + 1}.

Теперь множество Bj содержит длины всех найденных префиксов вектора Vj после подачи бита Ь в состоянии Т8.

3.3. Если ^ € Bj,то вектор Vj найден; полагаем Bj := Bj\{/+1}, Г[7 — 1] := 1.

4. Получили набор Т := (B1, B2,... , Bn), описывающий следующее состояние, и выходной символ автомата — вектор Г. Ищем набор Т среди имеющихся наборов То,... ,Т8.

Если нашли, что Т = Т^, то присваиваем в1 := Л,;

если такого состояния ещё нет, то добавляем его в таблицу в новую ячейку. Пусть номер этой ячейки в;. Тогда состояние Т8/ = Т.

5. Запоминаем ф(в,Ь) := в;, <^(в,Ь) := Г.

6. Если Ь = 0, то Ь := 1 и переход на шаг 3.

7. в := в + 1. Если в таблице есть состояние Т8, то переход на шаг 2.

8. Ответ: функции ф и <^.

2.3. П р и м е р п о и с к о в о г о б и т о в о г о а в т о м а т а Приведём пример битового автомата для поиска шаблонов 0111 и 1101 (таблица). Построенный автомат имеет семь состояний, в двух из которых возможен ненулевой выходной символ. Два состояния автомата (0 и 2) являются несущественными, то есть в них автомат может находиться только в начале обработки последовательности.

Таблица переходов и выходов автомата

Состояния Функция ф Функция <£>

0 1 0 1

То = (0, 0) 0 1 2 00 00

Т = ({1}, 0) 1 1 3 00 00

Т2 = (0, {1}) 2 1 4 00 00

Тз = ({2}, {1}) 3 1 5 00 00

Т4 = (0, {1, 2}) 4 6 4 00 00

Т5 = ({3}, {1, 2}) 5 6 4 00 10

Тб = ({1}, {3}) 6 1 3 00 01

2.4. П о с т р о е н и е б а й т о в о г о а в т о м а т а Имея автомат, принимающий на вход биты, можно построить автомат, принимающий на вход сразу пачки битов, например байты или полубайты. В любом случае будем называть такой автомат байтовым, а его входные векторы — байтами. Множество состояний у него будет таким же, входной алфавит {0,1}9, где д — число битов в байте; выходной алфавит будет чуть сложнее, поскольку в байтовом автомате возможно нахождение сразу нескольких вхождений одного шаблона в различных позициях. От выходного алфавита требуется способность передавать списки найденных шаблонов вместе с позициями. В программной реализации автор использовал целочисленный выходной алфавит и дополнительную таблицу соответствия номера выхода спискам найденных шаблонов.

При наличии битового автомата таблицы переходов и выходов байтового автомата строятся просто: по очереди обрабатываются все состояния автомата и все возможные значения байта. Для каждой пары входного байта и состояния анализ происходит так: битовый автомат устанавливается в соответствующее состояние и на его вход побитно подаётся входной байт. Все выходные сигналы автомата собираются вместе и запоминаются с учётом того, при подаче какого бита был получен выходной сигнал. Новое состояние байтового автомата должно соответствовать состоянию, в которое перешёл битовый автомат после подачи всех битов байта.

3. Затраты по памяти

Одним из ограничений применения поисковых автоматов является необходимость хранения таблиц переходов и выходов, которые могут занимать значительные объёмы памяти, поэтому их стоит оценить.

3.1. О ц е н к а к о л и ч е с т в а с о с т о я н и й п о и с к о в о г о а в т о м а т а Состояние автомата соответствует набору длин найденных префиксов искомых шаблонов. Пусть в некотором состоянии в самый длинный найденный префикс имеет длину /, и это префикс шаблона Vj. Тогда последние / битов, обработанных автоматом, совпадают с префиксом шаблона Vj и, следовательно, присутствие префиксов длины не больше / определено однозначно. Следовательно, любое состояние полностью определяется парой (7,/), соответствующей самому длинному найденному префиксу.

Если имеем всего п векторов с длинами к1, к2, ..., кп, то возможно всего (к1 — 1) пар вида (1,/), (к2 — 1) пар вида (2,/) и т.д. Помимо описанных, есть ещё нулевое

п

состояние. Получается, что всего возможно не больше £ kj — п + 1 состояний.

j=l

Автомат, ищущий один шаблон длины к, всегда имеет ровно к состояний, то есть оценка достижима. Отметим, что в примере из п. 2.3 эта оценка также достигается.

3.2. О ц е н к а о б ъ ё м а т а б л и ц п е р е х о д о в и в ы х о д о в

В программной реализации таблицы переходов и выходов объединены в одну таблицу, в ячейках которой вместе содержатся номер следующего состояния и индекс выхода. Сами выходы организованы в виде списков пар (номер шаблона, отступ позиции), описывающих найденные автоматом шаблоны, и хранятся в линейном массиве, называемом массивом выходных сигналов. Объём этого массива сильно зависит от вида шаблонов.

Минимальный объём массива выходных сигналов байтового автомата можно оценить числом пд, поскольку в любом бите байта может начаться любой шаблон. Однако среди выходов автомата могут встречаться не только единичные найденные шаблоны, но и списки нескольких найденных шаблонов, что может существенно увеличить объём массива. Практика показывает, что при достаточно большой длине шаблонов (как минимум, превышающей длину байта) этого обычно не происходит.

Для байтового автомата, полученного из битового автомата в примере из п. 2.3, объём массива выходных сигналов оказался очень значительным, что объясняется возможностью нахождения большого количества различных комбинаций искомых шаблонов после обработки очередного байта. Однако использование байтового автомата для поиска столь коротких шаблонов в любом случае не представляется разумным.

Оценим объём таблицы переходов и выходов. Число строк этой таблицы равно количеству состояний автомата, число столбцов — мощности входного алфавита. Для битового автомата оно равно 2, для байтового — 29.

В системах с восьмибитными байтами получаем 256 столбцов. Если состояние автомата и индекс выхода помещаются в машинное слово, то объём одной ячейки объединённой таблицы переходов и выходов занимает 4 байта, строка байтового автомата — 1024 байта. При большом количестве состояний объём таблиц может оказаться слишком большим для внутреннего высокоскоростного кэша процессора, особенно если речь идёт о специализированных процессорах сетевого оборудования или портативных устройств цифровой передачи данных. В этом случае стоит использовать автомат, получающий на вход половинки байтов, и обрабатывать каждый байт за два этапа. Это снизит скорость обработки приблизительно в 2 раза и немного усложнит реализацию, но уменьшит объём таблицы в 16 раз. Кроме того, уменьшится массив выходных сигналов.

4. Возможные обобщения

Описанную методику несложно обобщить на случай поиска неполностью определённых булевых векторов, заданных троичными векторами. Однако в этом случае оценка количества состояний будет отличаться, и, вероятно, в большую сторону. Другое возможное обобщение — это использование отличного от {0,1} алфавита для последовательности и искомых шаблонов.

5. Связь с известными алгоритмами

Описанный подход имеет много общего с алгоритмом поиска подстроки в строке Кнута — Морриса — Пратта (КМП) [2]. Оба метода предполагают предварительные вычисления, а затем требуют одну простую операцию на каждый символ входной последовательности.

Фактически битовый автомат для поиска одного шаблона реализует КМП-алго-ритм: каждому состоянию поискового автомата можно сопоставить число — максимальную длину найденного префикса шаблона. Это число совпадёт с длиной найденного префикса шаблона в алгоритме КМП; назовём его номером состояния. При совпадении очередного бита шаблона с битом потока в алгоритме КМП длина найденного префикса увеличивается на единицу, как и номер состояния поискового автомата. При несовпадении автомат откатится назад в состояние с номером, соответствующим значению префикс-функции алгоритма КМП.

Однако есть и существенные отличия:

1) Поисковый автомат способен искать сразу несколько шаблонов. Для поиска п шаблонов можно использовать п автоматов, ищущих по одному шаблону, однако, как видно из оценки количества состояний, суммарный объём таблиц этих автоматов неизбежно будет превышать объём автомата, ищущего сразу все п шаблонов. Кроме того, набору из п автоматов на каждый входной символ (бит, полубайт или байт) необходимо производить в п раз больше действий, чем одному автомату.

2) Поисковые автоматы способны принимать символы последовательности не только по одному, но и пачками.

Существует также сходство описываемых в данной работе поисковых автоматов с алгоритмом поиска подстроки в строке Ахо — Корасик [3], который тоже позволяет искать сразу набор шаблонов. Алфавит в этом алгоритме не обязательно двоичный, может быть произвольным. В алгоритме Ахо — Корасик используется конечный автомат, состояния которого образуют дерево. Узлы дерева соответствуют префиксам искомых шаблонов, как и в поисковых автоматах. Функционирование автомата Ахо — Корасик происходит аналогично функционированию описываемых в данной работе автоматов.

В [3] при подаче на вход автомата символа, который не может продолжить префикс, соответствующий текущему узлу, происходит дополнительный переход по так называемой суффиксной ссылке, что немного замедляет работу автомата. Вместо таблиц переходов и выходов хранится дерево состояний автомата. Количества состояний автомата Ахо — Корасик и поискового автомата, очевидно, совпадают. Для каждого состояния необходимо хранить всю информацию о соответствующем узле дерева состояний, которая включает набор ссылок на потомков и суффиксную ссылку. В случае двоичного алфавита суммарно будет не более двух ссылок. Дополнительно требуется хранить так называемую словарную суффиксную ссылку и признак, является ли узел словарным и какому шаблону он соответствует.

Однако вместо этого можно закодировать узлы дерева — они же состояния автомата — и составить таблицы переходов и выходов, получив таким образом тот же самый поисковый автомат, который предлагается в данной работе. Требуемый объём памяти и вычислительная сложность будут совпадать с поисковым автоматом.

В данной работе предлагается прямой алгоритм построения таблиц переходов и выходов без использования дерева состояний, а также автомат, принимающий на вход

сразу пачки битов или байты и позволяющий искать неполностью определённые булевы векторы.

Заключение

Предлагаемый поисковый автомат позволяет с очень высокой эффективностью одновременно искать в потоке данных несколько булевых векторов (шаблонов) некоторых длин. При этом с увеличением количества шаблонов объём требуемой памяти растёт медленнее, чем их суммарная длина, а трудоёмкость не изменяется совсем.

Для увеличения скорости обработки потока данных можно подавать биты потока на вход автомата пачками или байтами. При подаче битов пачками по q битов скорость обработки возрастёт в q раз, а объём требуемой памяти — в 2q раз.

Есть возможность обобщить алгоритм построения поискового автомата на поиск неполностью определённых булевых векторов, однако в этом случае объём требуемой памяти может превышать найденную оценку.

ЛИТЕРАТУРА

1. Агибалов Г. П., Оранов А. М. Лекции по теории конечных автоматов. Томск: Изд-во Том. ун-та, 1984. 185 с.

2. Knuth D. E., Morris J. H. Jr., and Pratt V.R. Fast pattern matching in strings // SIAM J. Comput. 1977. No. 6(2). P. 323-350.

3. AhoA.V. and CorasickM.J. Efficient string matching: An aid to bibliographic search // Commun. ACM. 1975. No. 18(6). P. 333-340.

i Надоели баннеры? Вы всегда можете отключить рекламу.