Гаразд, тому я не схожу на ідіот, я буду чіткіше викладати проблему / вимоги:
- Голка (візерунок) та стог сіна (текст для пошуку) - це рядки з нульовим завершенням у стилі C. Інформація про довжину не надається; при необхідності його необхідно обчислити.
- Функція повинна повернути вказівник на перший збіг, або
NULL
якщо не знайдено відповідності. - Випадки відмов не допускаються. Це означає, що будь-який алгоритм з непостійними (або великими постійними) вимогами для зберігання повинен мати резервний випадок для відмови розподілу (а продуктивність у догляді за резервним запасом сприяє найгіршій продуктивності).
- Реалізація повинна бути в C, хоча хороший опис алгоритму (або посилання на такий) без коду теж чудово.
... а також, що я маю на увазі під "найшвидшим":
- Детерміновано
O(n)
деn
= довжина стога сіна. (Але можливо використовувати ідеї алгоритмів, які зазвичай єO(nm)
(наприклад, прокатка хеша), якщо вони поєднуються з більш надійним алгоритмом для отримання детермінованихO(n)
результатів). - Ніколи не спрацьовує (помірно; пара годинників і
if (!needle[1])
т.д. добре) гірше, ніж алгоритм наївної грубої сили, особливо на дуже коротких голках, які, мабуть, є найпоширенішим випадком. (Беззастережна велика попередня обробка накладних витрат погана, оскільки намагаються покращити лінійний коефіцієнт для патологічних голок за рахунок ймовірних голок.) - З огляду на довільну голку та стоги сіна, порівнянні або кращі показники (не гірші на 50% довший час пошуку) порівняно з будь-яким іншим широко реалізованим алгоритмом.
- Окрім цих умов, я залишаю визначення «найшвидшого» відкритого типу. Хороша відповідь повинна пояснити, чому ви вважаєте підхід, який ви пропонуєте, "найшвидшим".
Моя поточна реалізація працює приблизно в 10% повільніше і в 8 разів швидше (залежно від вкладених даних), ніж реалізація двосторонньої програми glibc.
Оновлення: Мій поточний оптимальний алгоритм такий:
- Для голок довжиною 1 використовуйте
strchr
. - Для голок довжиною 2-4 використовуйте машинні слова, щоб порівнювати 2-4 байти одразу так: Попередньо завантажте голку в 16- або 32-бітове ціле число бітизмінами та оберніть старий байт / нові байти з стога сіна при кожній ітерації . Кожен байт копиці сіна читається рівно один раз і проводить перевірку проти 0 (кінець рядка) та одне 16- або 32-бітове порівняння.
- Для голок довжиною> 4 використовуйте Двосторонній алгоритм з поганою таблицею зсуву (наприклад, Boyer-Moore), який застосовується лише до останнього байта вікна. Щоб уникнути накладних витрат на ініціалізацію таблиці в 1 кб, що було б чистою втратою для багатьох голок середньої довжини, я зберігаю невеликий масив (32 байти), який позначає записи в таблиці зсуву. Біти, які не встановлені, відповідають значенням байтів, які ніколи не з’являються в голці, для яких можливий зсув повної довжини голки.
Основні питання, що залишилися в моїй думці:
- Чи є спосіб краще використовувати таблицю поганих змін? Бойер-Мур найкраще використовує його, скануючи назад (справа наліво), але для двостороннього потрібне сканування зліва направо.
- Єдині два алгоритми життєздатних кандидатів, які я знайшов для загального випадку (відсутність пам'яті та умов квадратичної продуктивності), - це двостороння та рядкова відповідність на упорядковані алфавіти . Але чи є легко виявлені випадки, коли різні алгоритми були б оптимальними? Звичайно, багато з
O(m)
(деm
довжина голки) в алгоритмах простору можуть бути використані для тогоm<100
чи іншого. Можливо також використовувати алгоритми, які є найгіршими квадратичними, якщо є простий тест на голки, які, очевидно, потребують лише лінійного часу.
Бонусні бали за:
- Чи можете ви покращити продуктивність, якщо припустити, що голка та стоги сіна є добре сформованими UTF-8? (Маючи символи різної довжини байтів, добре сформована гнучкість накладає деякі вимоги до вирівнювання рядків між голкою та стогом сіна та дозволяє автоматично змінювати 2-4 байтові зрушення, коли виникає невідповідний байт голови. Але ці обмеження купують вам багато / що більше, ніж що максимальні обчислення суфіксів, хороші зсуви суфіксу тощо вже дають різні алгоритми?)
Примітка. Я добре знаю більшість алгоритмів, які не існують, лише не наскільки вони добре працюють на практиці. Ось хороша довідка, щоб люди не продовжували давати мені посилання на алгоритми як коментарі / відповіді: http://www-igm.univ-mlv.fr/~lecroq/string/index.html
strstr
як щось пізніше, тому я насправді не навчився правильно читати папір, який ви зв'язали, але це звучить дуже багатообіцяюче. Дякую і вибачте за те, що не повернулися до вас.