Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Алгоритмы > Регулярное выражение, оператор "not" в NFA


Автор: rudvil 25.7.2010, 15:04
Как в регулярных выражениях выглядит NFA для оператора "^"?
Код
a^b
т.е. "a" но не "b"

С операторами:

"|" user posted image

"?" user posted image

"*" user posted image

"+" user posted image

все просто и понятно, а вот как быть с оператором "^"?

В гугле пусто, т.к. корректно сформулировать вопрос так и не удалось(NFA operator ^, NFA operator not, NFA ^)???

Автор: Pavia 25.7.2010, 17:12
Цитата(rudvil @  25.7.2010,  15:04 Найти цитируемый пост)
Как в регулярных выражениях выглядит NFA для оператора "^"?

В таблице состояний отрицательное и положительное меняется местами.
Цитата(rudvil @  25.7.2010,  15:04 Найти цитируемый пост)
все просто и понятно, а вот как быть с оператором "^"?

А никак, тут для упрощение отрицательные состояния не показаны.
И вообще оператор ^  обычно применяется только в "[]" скобках.

Автор: rudvil 25.7.2010, 17:35
Цитата
отрицательные состояния

первый раз слышу, пошел гуглить...
все равно, спасибо.

Автор: Pavia 25.7.2010, 18:31
Цитата(rudvil @  25.7.2010,  17:35 Найти цитируемый пост)
 пошел гуглить...

Гугл тебя думать не научит.

Автор: neutrino 25.7.2010, 18:46
Вот так думаю все станет понятно:

a(∑\{b})

Когда ∑ обозначает весь алфавит:

∑={a..z}U{0..9}U{@#$%^&*...}

Добавлено через 4 минуты и 56 секунд
Цитата(rudvil @  25.7.2010,  14:04 Найти цитируемый пост)
"a" но не "b"

Это лишено всякого смысла, ибо если а, то уж точно не б. Видимо имеется в виду: а, а потом все кроме б. Именно для этого случая я написал пояснение.

Автор: esperanto 25.7.2010, 22:36
Правильный ответ:

1) Имея НФА, строишь ДФА ему эквивалентный
2) Имея ДФА строишь его отрицание, посредством инверсии конечных состояний.
3) Полученный ДФА он же и НФА и есть нот от исходного автомата

Автор: neutrino 27.10.2010, 15:16
esperanto, А побыстрее никак?

Автор: rudvil 27.10.2010, 23:40
Чтобы упростить я остановился на решении как тут http://www.codeproject.com/KB/recipes/re_expression_parser.aspx
user posted image
т.е. если попали на dummy то дальше идти не будем.

Автор: esperanto 28.10.2010, 14:47
Цитата(neutrino @ 27.10.2010,  15:16)
esperanto, А побыстрее никак?

На курсе, вычислений учили именно так делать. Я не видел других решений в учебниких никогда. 

Автор: neutrino 28.10.2010, 16:30
rudvil, Да, но если мне нужно построить не отрицание одного символа, а отрицание целого регулярного выражения, то такой фокус не пройдет.

Добавлено через 54 секунды
Кстати, за ссылку спасибо. Интересно было почитать. Жаль я не читал ее до того, как реализовал свой регексп.

Автор: neutrino 2.11.2010, 21:49
esperanto, У меня не получилось реализовать такой вариант. 
Вот посмотри на этот регексп комментария в С например: "/*"(^("*/"))*"*/"
Здесь я выделил операторы красным. ^ - отрицание. * - Kleene closure (хрен знает как по-русски, ну сколько угодно повторений включая 0). Скобки задают приоритеты операторов. Можно прочитать этот регексп как: "/*"; все, что угодно кроме "*/"; "*/". Именно так задают подобные токены в Лексе и подобных тулах.

Нарисуй или опиши мне автомат, который принимает комментарии. Внимание! До комментария и после идут другие токены, т.е. мне необходим именно такой автомат, который бы мне нарезал ввод на токены, один из которых - комментарий.

Автор: rudvil 2.11.2010, 23:29
Цитата(neutrino @ 2.11.2010,  21:49)
"/*"(^("*/"))*"*/"

Не совсем верное рег. выражение.
Тут можно почитать про более универсальный регэксп http://ostermiller.org/findcomment.html
Код
/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+/

Автор: esperanto 2.11.2010, 23:35
Цитата(neutrino @ 2.11.2010,  21:49)
 Здесь я выделил операторы красным. ^ - отрицание.  .

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

Замыкание Клина наверное это называется

Автор: neutrino 3.11.2010, 00:53
Известно, что регулярные языки можно инвертировать и получить регулярный язык. В данном случае регулярное выражение - пример нотации. Дело в принципе. Как можно автомат такой создать?

Автор: esperanto 4.11.2010, 10:03
Тогда наверное так

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


Сложность экспоненциальная.

Автор: neutrino 4.11.2010, 12:27
Да, но в конце концов мне нужен автомат, а не регексп.
Думаю решение лежит где-то в области lookeahead-а, причем отрицательного. Т.е. когда я хочу найти токен, в котором нет "*/" (как в регекспе выше), то мне нужно матчить все у чего есть отрицательный lookahead "*/". Прикол еще ведь в том, что когда я сожрал "*/" и понял, что нужно вернуть токен до "*/", то я делаю как-бы откат назад. Как раз lookahead тут должен разрешить ситуацию.

Добавлено через 4 минуты и 54 секунды
rudvil, Не понятно к чему такой пост. Здесь мы разбираем теорию, а не занимаемся поиском наиболее точного регекспа. И если уж вы идете в этом направлении, то гораздо проще использовать т.н. lazy quantification, частности non-greedy quantifier.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)