Ось проблема, яка мене клопоче певний час. Скажімо, рядок - це послідовність 1s і 0s, а wildcard - послідовність 1, 0 і? S. Всі рядки та рядки підкреслення мають однакову довжину. Це стандартні символи UNIX; 10 × 1 відповідає 10011, 10111 тощо - a? відповідає 1 або 0 у цій позиції. Якщо і це рядкові підстановки, то запишемо якщо кожна рядок, відповідна , також відповідає .
Проблеми : з урахуванням набору рядків підстановки та запиту (також рядок підстановки), чи існує такий, що ? А якщо ні, то чи можемо ми ефективно додати до ?
Ось очевидне рішення (де - розмір рядків, - розмір слова ОЗУ (як правило, 32 або 64)): пройдіть кожен елемент списку та протестуйте умова (яка може бути виконана за 2 або 3 операції з використанням біт-подвійності). Також перевіряйте, чи утримує будь-який елемент під час сканування. Якщо провалить наш тест, то додайте до набору та видаліть , який ми позначили.
Але це не досить швидко. Було б дуже здорово, якби існувало рішення , або, в ідеальному світі, за складністю, схожим на дерево з радіацією ( ). Також добре, щоб запити були приблизно правильними : тобто, якщо , повертайте так чи ні; але якщо умова не виконується, точно не поверніть ні.
Хоча це не допомагає в найгіршому випадку складності, можна припустити, що всі елементи в обмежені рядком підстановки; тобто існує деякий такий, що для всіх , .
Ідеї, які я пробував
- Підстановочні рядки утворюють з'єднання-напіврешітку. У нас може бути дерев яне дерево, яке містить рядки підстановки; листя були б рядковими рядками, а гілки представляли б з'єднання всіх дітей. Якщо запит і об'єднання є незрівнянними, то нам не доведеться витрачати час на спроби порівняти всіх дітей цієї галузі. Крім того, якщо ми зробимо оновлення, і оновлення буде більшим за об'єднання, ми можемо просто видалити всю гілку. На жаль, це все-таки в гіршому випадку, і ми не завжди знаходимо "найкращі" об'єднання, які можна зробити при скануванні через дерево, щоб додати елементи.
- Можна сформувати базисне з синтаксичного дерева . Ми знаємо, що обмежений якоюсь рядовою лінією; припустимо, що це? 0? 0. Тоді всі гілки трійки повинні бути лише на 1-му та 3-му розрядах рядків. Якщо поточний біт, на який ми розгалужуємо запит, є 1, ми повинні перевірити? і 1 гілки; якщо це 0, ми перевіряємо? і 0 гілок; якщо це так, ми лише перевіряємо? відділення. Оскільки ми маємо потенційно взяти кілька гілок, це здається не дуже гарним (важко оновити трійку з тієї ж причини). Оскільки відповідність - це дуже швидка операція, боляче порівняно з наївною стратегією робити багато обходу дерева (слідування за цілою купою покажчиків набагато дорожче, ніж виконання деяких АБО та ІН).
Пов'язані роботи
У мережевій спільноті ця проблема проявляється як "класифікація пакетів", ось добре опитування відомих алгоритмів та структур даних . На жаль, майже завжди робиться припущення, що рядки підстановки відповідають лише префіксам, а запит є кортежем таких рядків. Звичайно, ми завжди можемо перетворити загальну рядок підстановки, щоб відповідати цим критеріям: 1? 00? 1 ?? є (1,?, 0, 0,?, 1,?,?). Однак це не буде ефективно. Інше припущення, що ці кортежі пов'язані з "кольором", і запит повинен повернути колір (не тільки те, що він збігався). Це значно ускладнює проблему, оскільки нам потрібно замовити кортежі (інакше неоднозначно, який з (0,?) Та (?, 1) відповідає (0, 1)).
У спільноті алгоритмів я знайшов чимало результатів, пов’язаних із пошуком підрядків, які відповідають "не цікавить". Це набагато важча проблема, і я не можу реально використовувати жодну з методик.
На закінчення
Дякуємо за будь-яку допомогу!