RodionGork's blog

By RodionGork, 13 years ago, In Russian

Уважаемые товарищи!

Буду очень признателен если кто-то более умный чем я подскажет оптимизацию алгоритма.

Постановка задачи

Фрагменты строки сравниваются с фрагментами образца с применением нечёткого сравнения.

Входная строка текста разбивается на фрагменты (например, на отдельные слова) и дальше рассматривается как последовательность таких слов:
[T1, T2, ..., Tn]

Образец (шаблон) для сравнения может содержать элементы 3 типов (возможно, вложенные):
1. "Простой" - представляется как последовательность символов в кавычках - например, "стол" - и сравнивается с одиночным словом, давая результат от 0.0 (совсем непохожи) до 1.0 (идентичны).
2. "Последовательность" - представляется как набор дочерних элементов, разделённых запятыми, например "стол", "стоит", "у", "стены". Сравнивает по порядку следования дочерние элементы со словами входного текста.
3. "Выбор" - представляется как набор дочерних элементов разделённых символом "|", например "стол" | "буфет" | "кровать".

Пример сложного шаблона:
("стол" | "буфет" | "кровать"), "стоит", (("у", "стены") | ("на", "полу"))

Как найти результат сравнения со сложным шаблоном?

Естественным казалось ввести такие правила:
а) Результатом "Последовательности" является среднее геометрическое результатов дочерних элементов.
б) Результатом "Альтернативы" является максимальный из результатов дочерних элементов.

Однако возникает проблема в шаблонах содержащих вложенные "последовательности", например:
( "bla" | ("ola", "gde") ) , "chmoda"
Сравним это с "bla ide chmoda" - тогда "альтернатива" выберет лучшим вариант "bla" т.к. он даёт 1.0 тогда как "ola", "gde" даёт только 0.66, однако после этого остаток строки составит два слова "ide chmoda" и сравнение с просто "chmoda" даст для них 0.0, и общий результат будет 0.0.
В то же время, если был бы выбран для "альтернативы" второй вариант, то остаток строки сравнился бы идеально и общий результат был около 0.76.

Простая идея - перенумеровать все простейшие элементы в шаблоне:
("bla"=E1, "ola"=E2, "gde"=E3, "chmoda"=E4)
И построить все возможные варианты сравнения:
E1:T1, E4:T2
E2:T1, E3:T2, E4:T3
Если теперь вычислить среднее геометрическое результатов, приняв T1=bla, T2=ide, T3=chmoda, то мы конечно найдём оптимальный вариант.

Однако это неэффективно, т.к. например:
("bla"|("ola","gde")),("xyz"|"pur"|"lti")
здесь будет уже 6 вариантов, но для строки "bla ide xaz" сравнение "pur" или "lti" с "xaz" дало бы 0.0, и если определить это заранее, то 4 из 6 вариантов можно было бы не рассматривать (тк. ср. геометрическое всё равно будет 0.0). Но как такие вещи "определять заранее"?..

В общем, буду благодарен светлым головам... Также будет неплохо если кто-то укажет что задача сводится тем или иным образом к какой-то из известных...

с уважением,
Родион

P.S. Не подумайте плохого, это не учебная задача и не попытка протестировать гениальность сообщества. Я пытался рожать опенсорсную либку, которая такими вещами занимается (ну только капельку сложнее) - и только сейчас обратил внимание на неадекватность алгоритма (она довольно в редких случаях проявляется). Так что если кто мечтает "вложиться" в опенсорсный проектик идеей - милости прошу.

  • Vote: I like it
  • +17
  • Vote: I do not like it