Автор Тема: Сопоставление с образцом  (Прочитано 42551 раз)

Kemet

  • Hero Member
  • *****
  • Сообщений: 587
    • Просмотр профиля
Re: Сопоставление с образцом
« Ответ #30 : Сентябрь 20, 2012, 04:49:46 pm »
а чем рекурсия не угодила?

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re: Сопоставление с образцом
« Ответ #31 : Сентябрь 20, 2012, 05:20:32 pm »
Но пока еще не осознал куда деть рекурсию, максимальная глубина которой равна колчичеству подстрок (звездочек).

Да, можно без рекурсии, достаточно помнить позицию последней звезды (как у Berserker'а). Потому что очередная найденная звезда "эквивалентна" предыдущей с точки зрения нахождения соответствия.

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re: Сопоставление с образцом
« Ответ #32 : Сентябрь 20, 2012, 05:27:17 pm »
а чем рекурсия не угодила?

В данном случае - все хорошо (ну не будет мильена звездочек в образце). Собственно я у себя и оставил как есть, потому что с рекурсией код проще, а сложность O - одинаковая. Просто хотелось понять как можно без нее. А еще без рекурсии можно полноценный злобнейший цикл Дейкстры наколбасить с трехэтажными условиями в ифах ;)

Илья Ермаков

  • Sr. Member
  • ****
  • Сообщений: 493
    • Просмотр профиля
Re: Сопоставление с образцом
« Ответ #33 : Сентябрь 20, 2012, 05:27:37 pm »
2 vlad:
Если тебе нужна рекурсия, значит, ты построил недетерминированный КА (в котором из некоторого состояния могут быть два и более перехода, помеченные одним символом). Его можно формально преобразовать в детерминированный, в котором очередной символ однозначно определяет переход.


Berserker

  • Sr. Member
  • ****
  • Сообщений: 254
    • Просмотр профиля
Re: Сопоставление с образцом
« Ответ #34 : Сентябрь 20, 2012, 05:55:04 pm »
Надо бы ещё поддержку "?" добавить в качестве 1-го случайного символа. Кстати, FindFirstFile "по-своему" сопоставляет с шаблоном, так что:

"*.pak" вернёт и "abba.pak.abba".

Berserker

  • Sr. Member
  • ****
  • Сообщений: 254
    • Просмотр профиля
Re: Сопоставление с образцом
« Ответ #35 : Сентябрь 20, 2012, 05:59:20 pm »
а чем рекурсия не угодила?
Поправьте меня, если я ошибаюсь, но разве у Петра не на каждый символ вызов процедуры? Очень лаконичный и надёжный вариант, но переполнение стопки не дремлет.

На пользовательских данных плохой запрос повесит функцию (сложность N^2 поиска строки в лоб) на неопределённое время, а в случае рекурсии убьёт процесс.

Найти a[99]
Дано a[98]b
В скобках - число повторений.
Проходы: 99, 98, 97...
« Последнее редактирование: Сентябрь 20, 2012, 06:03:13 pm от Berserker »

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re: Сопоставление с образцом
« Ответ #36 : Сентябрь 20, 2012, 06:00:01 pm »
Надо бы ещё поддержку "?" добавить в качестве 1-го случайного символа.

Вообще в оригинале надо сделать вот это: http://msdn.microsoft.com/en-us/library/ms179859.aspx

Berserker

  • Sr. Member
  • ****
  • Сообщений: 254
    • Просмотр профиля
Re: Сопоставление с образцом
« Ответ #37 : Сентябрь 20, 2012, 06:05:16 pm »
В принципе, удобная конструкция. Нужно будет попробовать в полном объёме сделать.

albobin

  • Full Member
  • ***
  • Сообщений: 198
    • Просмотр профиля
Re: Сопоставление с образцом
« Ответ #38 : Сентябрь 20, 2012, 06:48:14 pm »
но переполнение стопки не дремлет.

На пользовательских данных плохой запрос повесит функцию (сложность N^2 поиска строки в лоб) на неопределённое время, а в случае рекурсии убьёт процесс.

Найти a[99]
Дано a[98]b
В скобках - число повторений.
Проходы: 99, 98, 97...
В той программе у P.A. при поиске последней непустой подстроки образца в проверяемой строке неявным образом учитывается  "наличие" как бы символа "конца строки" и потому окончательное успешное сравнение естественно может произойти только когда правые границы совпадут, но по алгоритму процесс  сравнения "тупо" повторяется двигаясь шаг за шагом вправо.
122222222222  и 1*2
Вот двойка и будет ползти по строке начиная с 1 позиции пока не упрётся в правую границу, и только тогда окончательный итог будет TRUE.
Вот почему лучше сначала проверить на соответствие непустые крайние  подстроки образца, а серединку оставить на десерт. :)


 

Valery Solovey

  • Hero Member
  • *****
  • Сообщений: 509
    • Просмотр профиля
Re: Сопоставление с образцом
« Ответ #39 : Сентябрь 20, 2012, 08:14:03 pm »
в котором очередной символ однозначно определяет переход.
Дело не в КА. Потому что главный вопрос при очередном шаге не "куда?", а "когда?". И правильный ответ на него "в будущем". Дело в том, что есть не меньше двух подходов к регулярным выражениям. Например, сопоставление 123412341234
1.*1234
одним методом вернёт FALSE (и это правильно), а другая вернёт TRUE (и это тоже правильно).
Но только в сообщении 36 Vlad дал необходимый минимум исходных данных, чтобы начать решать задачу, поэтому вариант только на опору КА, без запоминания состояния, не подойдёт.

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re: Сопоставление с образцом
« Ответ #40 : Сентябрь 21, 2012, 04:51:09 am »
Полный текст на C#. Не причесывал для Assert'ов.

Голосую за твой вариант как наиболее красивый и наглядный :)

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re: Сопоставление с образцом
« Ответ #41 : Сентябрь 21, 2012, 04:57:12 am »
Поправьте меня, если я ошибаюсь, но разве у Петра не на каждый символ вызов процедуры? Очень лаконичный и надёжный вариант, но переполнение стопки не дремлет.

Там типичная хвостовая рекурсия (которая последняя) - компилятор имеет все шансы соптимизить ее в цикл.  Но не факт, конечно. А та, которая в цикле - зависит от количества звездочек, а не всех символов (как и в моем варианте).
« Последнее редактирование: Сентябрь 21, 2012, 04:59:46 am от vlad »

Kemet

  • Hero Member
  • *****
  • Сообщений: 587
    • Просмотр профиля
Re: Сопоставление с образцом
« Ответ #42 : Сентябрь 21, 2012, 11:00:06 am »
Если без рекурсии, то как-то так:
MODULE Match;
IMPORT Strings;

PROCEDURE MatchIt( CONST text, pattern : ARRAY OF CHAR;
                         posT, posP    : LONGINT;
                         lenT, lenP    : LONGINT ): BOOLEAN;

VAR chT, chP: CHAR;

  PROCEDURE NoMoreCharInPattern(): BOOLEAN;
  BEGIN
    WHILE ( pattern[ posP ] = '*' ) & ( posP # lenP ) DO
      INC( posP );
    END;
    RETURN posP = lenP;
  END NoMoreCharInPattern;

  PROCEDURE FindCharInText( ch: CHAR ): BOOLEAN;
  BEGIN
    WHILE posT # lenT DO
      IF text[ posT ] = ch THEN RETURN TRUE END;
      INC ( posT );
    END;
    RETURN FALSE;
  END FindCharInText;

BEGIN
  LOOP
    IF posT = lenT THEN
      RETURN NoMoreCharInPattern();
    ELSIF posP = lenP THEN
      RETURN FALSE;
    ELSE
      chT := text[ posT ];
      chP := pattern[ posP ];
      IF chP = '*' THEN
        INC( posP );
        IF NoMoreCharInPattern() THEN
          RETURN TRUE;
        ELSIF FindCharInText( pattern[ posP ] ) THEN       
          INC( posT );
          INC( posP );
        ELSE
          RETURN FALSE;
        END;
      ELSIF ( chP = chT ) OR ( chP = '?' ) THEN
        INC( posT );
        INC( posP );
      ELSE
        RETURN FALSE;
      END;
    END;
  END;
END MatchIt;

PROCEDURE DoMatch*( CONST text, pattern: ARRAY OF CHAR ): BOOLEAN;
BEGIN
  RETURN MatchIt( text, pattern, 0, 0, Strings.Length( text ), Strings.Length( pattern ));
END DoMatch;

END Match.
'?' вроде тоже должна работать, при условии, что стоит не перед звездой, но кто ее перед звездой ставит...

Kemet

  • Hero Member
  • *****
  • Сообщений: 587
    • Просмотр профиля
Re: Сопоставление с образцом
« Ответ #43 : Сентябрь 21, 2012, 11:09:07 am »
'?' вроде тоже должна работать, при условии, что стоит не перед звездой, но кто ее перед звездой ставит...
Вернее не рядом со звездой

Berserker

  • Sr. Member
  • ****
  • Сообщений: 254
    • Просмотр профиля
Re: Сопоставление с образцом
« Ответ #44 : Сентябрь 21, 2012, 11:53:33 am »
Убеждаюсь лишний раз, что RETURN/BREAK/EXIT - зло.

Если пока оставить вопрос с комбинациями * и ?, у меня серьёзные подозрения, что

abdabc *abc не пройдёт. Нет откатов. По шагам:

* - найди "a" => ok
b = b? да
d = c? нет, конец игры.

Или я ошибаюсь?