Механизмы DFA и NFA: в чем разница их возможностей и ограничений?

Я ищу нетехническое объяснение разницы между механизмами DFA и NFA, основанное на их возможностях и ограничениях.


person blunders    schedule 20.10.2010    source источник
comment
en.wikipedia.org/wiki/Deterministic_finite-state_machine   -  person SilentGhost    schedule 20.10.2010
comment
@SilentGhost Я знаю, что это не сложно по математике, но эта статья зависит от того, кто знает всю математическую символику, которую они не объяснили. Как и многие статьи в Википедии, она была написана кем-то, кто так хорошо знает предмет, что не может увидеть его с точки зрения новичка, и давайте признаем, что это тот, кто будет читать статью больше всего.   -  person Andrew S    schedule 15.03.2014


Ответы (5)


Детерминированные конечные автоматы (DFA) и недетерминированные конечные автоматы (NFA) имеют точно такие же возможности и ограничения. Единственная разница заключается в удобстве записи.

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

Детерминированный конечный автомат находится в одном состоянии в каждый момент времени, что реализуемо. Недетерминированный конечный автомат может находиться более чем в одном состоянии одновременно: например, в языке, где идентификаторы могут начинаться с цифры, может быть состояние «чтение числа» и другое состояние «чтение идентификатора», а также NFA может быть в обоих одновременно при чтении чего-либо, начинающегося с «123». Какое состояние на самом деле применяется, будет зависеть от того, встретило ли оно что-то нечисловое перед концом слова.

Теперь мы можем выразить «чтение числа или идентификатора» как само состояние, и вдруг нам не понадобится NFA. Если мы выразим комбинации состояний в NFA как сами состояния, мы получим DFA с гораздо большим количеством состояний, чем NFA, но который делает то же самое.

Вопрос в том, что легче читать, писать или с чем иметь дело. DFA легче понять сами по себе, но NFA, как правило, меньше.

person David Thornley    schedule 20.10.2010
comment
Хорошо, теперь удаленный ответ перепутал NFA с DFA. Я видел, как люди делали это раньше, и, по-видимому, это связано с полезной книгой, или, во всяком случае, так утверждается: fanf.livejournal.com/37166.html - person Eamon Nerbonne; 20.10.2010

Вот нетехнический ответ от Microsoft:

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

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

Механизмы POSIX NFA аналогичны традиционным механизмам NFA, за исключением того, что они продолжают откат до тех пор, пока не смогут гарантировать, что они нашли максимально возможное совпадение. В результате механизм POSIX NFA работает медленнее, чем традиционный механизм NFA, и при использовании POSIX NFA вы не можете предпочесть более короткое совпадение более длинному, изменив порядок поиска с возвратом.

Программисты предпочитают традиционные механизмы NFA, потому что они более выразительны, чем механизмы DFA или POSIX NFA. Хотя в худшем случае они могут работать медленно, вы можете настроить их так, чтобы они находили совпадения за линейное или полиномиальное время, используя шаблоны, которые уменьшают неоднозначность и ограничивают поиск с возвратом.

[http://msdn.microsoft.com/en-us/library/0yzc2yb0.aspx]

person james.garriss    schedule 26.01.2011
comment
Статья MSDN вводит в заблуждение; NFA и DFA одинаково эффективны. Алгоритмы NFA не требуют обратного отслеживания (который имеет экспоненциальное поведение в худшем случае). Причина необходимости обратного отслеживания заключается в том, что регулярные выражения намного мощнее (например, обратные ссылки), чем обычные языки, и поэтому они не могут быть смоделированы каноническими NFA/DFA. Пример хорошо реализованного алгоритма NFA, который не использует возврат: swtch.com/~rsc/ регулярное выражение/regexp1.html - person Rufflewind; 15.06.2013
comment
На тему катастрофического возврата: stackstatus.net/post/147710624694/< /а> - person Eamon Nerbonne; 20.07.2016
comment
Статья MS на самом деле неверна, если вы придерживаетесь стандартных определений: NFA вообще не отступает. Некоторые автоматы с возвратом легче реализовать, если вы начинаете с NFA, и, возможно, статья относится к такой реализации. - person toolforger; 01.12.2018

Простое нетехническое объяснение, перефразированное из книги Джеффри Фридла Mastering Regular Expressions.

ВНИМАНИЕ:

Хотя эта книга обычно считается «библией регулярных выражений», возникают некоторые разногласия относительно того, действительно ли правильно проведенное здесь различие между DFA и NFA. Я не ученый-компьютерщик, и я не понимаю большую часть теории, лежащей в основе того, что на самом деле является «регулярным» выражением, детерминированным или нет. После того, как разгорелся спор, я удалил этот ответ из-за этого, но с тех пор на него ссылаются в комментариях к другим ответам. Мне было бы очень интересно обсудить это дальше — неужели Фридль действительно ошибается? Или я неправильно понял Фридла (но я перечитал эту главу вчера вечером, и это точно так же, как я вспомнил...)?

Редактировать: Похоже, мы с Фридлом действительно ошиблись. Пожалуйста, ознакомьтесь с отличными комментариями Эймона ниже.


Исходный ответ:

Подсистема DFA проходит через входную строку символ за символом и пробует (и запоминает) все возможные способы совпадения регулярного выражения на данном этапе. Если он достигает конца строки, он объявляет успех.

Представьте строку AAB и регулярное выражение A*AB. Теперь мы пройдемся по нашей строке буква за буквой.

  1. A:

    • First branch: Can be matched by A*.
    • Вторая ветвь: можно сопоставить, игнорируя A* (допускаются нулевые повторения) и используя второй A в регулярном выражении.
  2. A:

    • First branch: Can be matched by expanding A*.
    • Вторая ветвь: Не может быть сопоставлена ​​с B. Вторая ветвь не работает. Но:
    • Третья ветвь: можно сопоставить, не расширяя A* и используя вместо этого вторую A.
  3. B:

    • First branch: Can't be matched by expanding A* or by moving on in the regex to the next token A. First branch fails.
    • Третья ветвь: Можно сопоставить. Ура!

Механизм DFA никогда не выполняет возврат в строке.


Подсистема NFA проходит через токен regex за токеном и пробует все возможные перестановки в строке, при необходимости откатываясь назад. Если он достигает конца регулярного выражения, он объявляет об успехе.

Представьте себе ту же строку и то же регулярное выражение, что и раньше. Теперь мы проходим через наш токен регулярного выражения за токеном:

  1. A*: Сопоставьте AA. Запомните позиции возврата 0 (начало строки) и 1.
  2. A: Не совпадает. Но у нас есть обратная позиция, к которой мы можем вернуться и попробовать еще раз. Механизм регулярных выражений отступает на один символ. Теперь A совпадает.
  3. B: Совпадает. Достигнут конец регулярного выражения (остается одна свободная позиция возврата). Ура!
person Tim Pietzcker    schedule 20.10.2010
comment
@Tim_Pietzcker: Спасибо, что тоже опубликовали шаги по движку NFA. Удалил другой вопрос... :-) - person blunders; 20.10.2010
comment
Этот ответ неточен - катастрофический возврат назад ортогонален всему различию NFA/DFA. И то, что вы описываете как DFA, на самом деле является NFA (с использованием типичной суперпозиции состояний) - DFA всегда находятся только в одном состоянии, следовательно, детерминированы, а NFA могут находиться в нескольких состояниях, следовательно, недетерминированы. - person Eamon Nerbonne; 20.10.2010
comment
В каком-то смысле это всего лишь терминология. Сказав это, DFA являются детерминированными (и это в названии), а NFA недетерминированными (опять же, как следует из названия). У этого есть довольно простая причина: DFA всегда находится ровно в одном состоянии, а когда представлен символ, всегда есть одно уникальное (детерминированное) следующее состояние, которому всегда соответствует символ. Итак, ваше первое объяснение - прекрасный алгоритм регулярных выражений, но это не DFA - очевидно, и, как вы описываете, может быть несколько вариантов, и вы никогда не знаете, какой из них лучше, пока строка не закончится. - person Eamon Nerbonne; 21.10.2010
comment
Ваш второй алгоритм, помеченный как движок NFA, действительно является одной из возможных реализаций NFA. Он разрешает ту же неоднозначность, что и ваш первый (также NFA) алгоритм по-разному: а именно, просто выбирая один вариант и возвращаясь по мере необходимости. Итак, это действительно NFA, но это не единственно возможный NFA, как показывает ваш первый метод: он по-разному работает с одним и тем же недетерминизмом. Я полагаю, вы могли бы назвать это движком NFA с возвратом, чтобы различать их. - person Eamon Nerbonne; 21.10.2010
comment
Наконец, ничего не стоит тот факт, что в любом автомате с конечным состоянием, как следует из названия, состояния являются конечными — более конкретно, после встраивания в состояние любой соответствующей информации этот кортеж по-прежнему необходимо иметь конечное число вариантов. И это означает, что, строго говоря, perl-совместимые движки на самом деле не являются каким-либо типом FSA, ни DFA, ни NFA: в конце концов, вы можете включать обратные ссылки произвольной длины, и существует бесконечное количество строк произвольной длины. - person Eamon Nerbonne; 21.10.2010
comment
Различие критически важно для производительности, потому что бесконечное пространство состояний означает, что вы не можете предварительно скомпилировать NFA или эффективно выполнить его с использованием первого алгоритма. В общем случае откат прерывается, когда сталкиваются с регулярными выражениями (и вы сталкиваетесь с такими на практике), которые вызывают катастрофический возврат. - person Eamon Nerbonne; 21.10.2010
comment
Таким образом, могут быть какие-то средства, отличные от NFA, для эффективного выполнения обратных ссылок (я подозреваю, что они действительно есть), но NFA нельзя использовать для работы с обратными ссылками. Строго говоря, они вообще не могут этого сделать, а грубо говоря и допуская неограниченную аннотацию, они не могут сделать это надежно. - person Eamon Nerbonne; 21.10.2010
comment
@Eamon: Большое спасибо за эту полезную информацию. Жаль, что голосование за ваши комментарии не даст вам репутацию. - person Tim Pietzcker; 21.10.2010
comment
@Eamon Nerbonne: Извините, но до того, как я пришел к вашему объяснению, все было ясно. Вы имеете в виду, что оба примера являются NFA. Я вроде согласен. Я понимаю, почему DFA не может обрабатывать все продвинутые (фактически нерегулярные) регулярные выражения. Чего мне не хватает, так это примера DFA для простых регулярных выражений. Или вы согласитесь, что первый пример можно преобразовать в DFA, определив состояния DFA как наборы состояний NFA и просто перефразировав алгоритм? - person maaartinus; 14.11.2013
comment
Да, это почти все. В Википедии есть пример NFA и пример DFA. - person Eamon Nerbonne; 15.11.2013

И NFA, и DFA являются конечными автоматами, как следует из их названий.

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

В таблице состояний DFA каждый ключ <state₀, input> будет переходить к одному и только одному state₁.

В таблице состояний NFA каждый <state₀, input> будет переходить в набор состояний.

Когда вы берете DFA, сбрасываете его в начальное состояние, задаете ему последовательность входных символов, и вы точно будете знать, в каком конечном состоянии он находится, и является ли это состоянием успеха или нет.

Однако когда вы берете NFA, он будет для каждого входного символа искать набор возможных состояний результата и (теоретически) случайным образом, недетерминировано, выбирать одно из них. Если существует последовательность случайных выборок, которая приводит к одному из состояний успеха для этой входной строки, то говорят, что NFA завершился успешно для этой строки. Другими словами, вы должны притворяться, что он волшебным образом всегда выбирает правильный.

Один из первых вопросов в вычислительной технике заключался в том, являются ли NFA более мощными, чем DFA, из-за этой магии, и ответ оказался нет, поскольку любой NFA можно было преобразовать в эквивалентный DFA. Их возможности и ограничения в точности совпадают друг с другом.

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

person BenGoldberg    schedule 22.10.2016
comment
Является ли тогда, что DFA считается успешным для этой строки, предназначенной вместо NFA? - person Scratte; 04.02.2021

Я считаю объяснение, данное в Regular Expresss, The Complete Tutorial Яном Гойвартсом, наиболее полезным. См. стр. 7 этого PDF-файла:

https://www.princeton.edu/~mlovett/reference/Regular-Expressions.pdf

Среди других замечаний, упомянутых на странице 7, существует два типа механизмов регулярных выражений: механизмы, ориентированные на текст, и механизмы, ориентированные на регулярные выражения. Джеффри Фридл называет их двигателями DFA и NFA соответственно. ... некоторые очень полезные функции, такие как ленивые квантификаторы и обратные ссылки, могут быть реализованы только в механизмах, ориентированных на регулярные выражения.

person RBV    schedule 26.04.2016
comment
Я считаю, что эта ссылка была основой того, что сейчас является Regular-Expressions.info Это тот же автор, и я распознать некоторые фразы. - person Scratte; 04.02.2021