задача
Задача состоит в том, чтобы сыграть в гольф алгоритм точного сопоставления строк в реальном времени по вашему выбору.
вход
Две строки текста поступают на стандартный ввод, разделенные новой строкой. Первая строка содержит «шаблон» и будет просто строкой ASCII, нарисованной из букв a-z
.
Вторая строка содержит более длинный «текст» и также будет просто строкой ASCII, взятой из букв a-z
.
Выход
Список индексов, где встречаются точные совпадения. Вы должны вывести позицию начала каждого совпадения.
Спецификация
Ваш алгоритм может потратить линейное время на предварительную обработку шаблона. Затем он должен прочитать текст слева направо и занять постоянное время для каждого символа в тексте и вывести любое новое совпадение, как только оно произойдет. Матчи, конечно, могут перекрывать друг друга.
Алгоритм
Существует много алгоритмов точного соответствия в реальном времени. Один из них упоминается в вики для KMP, например. Вы можете использовать любой, который вам нравится, но вы всегда должны выводить правильный ответ.
Я буду вести таблицу лидеров по языкам, чтобы те, кто предпочитает популярные языки, также могли победить по-своему. Пожалуйста, объясните, какой алгоритм вы реализовали.
Реальное время
Кажется, было много путаницы в том, что означает в реальном времени. Это не просто означает линейное время. Таким образом, стандартный KMP не в режиме реального времени. Ссылка в вопросе явно указывает на часть вики-страницы для KMP о варианте KMP в реальном времени. Бойер-Мур-Галиль не в режиме реального времени. В этом общем вопросе / ответе обсуждается проблема, или можно просто Google "точное соответствие в реальном времени" или аналогичные термины.
источник
abcd
иacbdefg
я бы вывел1 4
, дляa
иd
?a
иd
совпадают. Естьabcd
иacbdefg
, и тоa
иd
находятся в одинаковых позициях.Ответы:
Python 2, 495 байт
Это KMP в реальном времени, который намного короче и лишь немного медленнее, чем алгоритм BMG (который обычно является сублинейным). Позвонить с
K(pattern, text)
; вывод идентичен алгоритму BMG.источник
Python 2, 937 байт
Это не коротко, во всяком случае, но это (а) работает, (б) удовлетворяет всем требованиям, и (в) играет в гольф столько, сколько я могу сделать это.
Это реализация алгоритма Бойера-Мура-Галиля. Довольно просто - позвоните с
S(pattern,text)
; две другие функции используются в предварительной обработке. Действительно, все, кроме последних 5 строк, является предварительной обработкой.Пример запуска, который занял около секунды:
источник
O(m)
предварительной обработке иO(n)
сопоставлении [=>O(n+m)
], что и делает (или лучше).O(n+m)
времени, но, к примеру, потребуется n времени для одного из символов в тексте.KMP, Python 2 (213 байт)
Безголовая версия. Первый цикл - создание автоматов KMP. Второй цикл идет по автоматам. Они имеют почти одинаковый шаблон, но абстрагирование их будет стоить больше байтов, поэтому для гольф-кода я бы предпочел повторить эту логику. Подобная реализация на самом деле широко используется в программировании конкурсов.
источник
KMP в реальном времени, Python 2 (167 байт)
В обычном KMP мы моделируем поведение автомата с помощью функции сбоя. В этом KMP в реальном времени полный автомат построен так, что в соответствующей фразе он может обрабатывать каждый символ в реальном времени (постоянное время).
Временная и пространственная сложность предварительной обработки составляет O (нм), где m - размер алфавита, а n - длина строки шаблона. Однако в моих тестах фактический размер таблицы переходов всегда меньше 2n, поэтому, возможно, мы сможем доказать, что сложность времени и пространства равна O (n).
Неуправляемая версия
источник
Q, 146 байт
Тестовое задание
генерирует 15 и 34
Примечания
Не ограничивается алфавитом (поддерживает любые символы ascii и учитывает регистр).
Не использует какие-либо конкретные операции, определенные Q над строками -> работает со строками как с последовательностями (совпадение операций, длина и т. Д.)
Минимизирует таблицу переходов, объединяя все символы, не входящие в шаблон, как один уникальный класс символов.
Я могу немного сжать код. Это первая попытка проверить стратегию решения
Посетите любой символ текста ровно один раз, и для каждого входного символа есть уникальный переход. Итак, я предполагаю, что поиск соответствует «реальному времени»
Построение таблицы al состояния i и char c ищут самую длинную подстроку, которая заканчивается в i и после добавления c является префиксом S. Конструкция не оптимизирована, поэтому я не знаю, является ли она действительной
Формат ввода не очень хорошо сочетается с языком. Передача двух строковых аргументов сэкономит 16 байт
объяснение
глобальный W представляет шаблон, а S соответствует тексту для поиска
x:1_"\n "\:x
странный код, чтобы справиться с требованиями ввода (Q требует, чтобы многострочные строки имели отступы не первых строк, поэтому он должен отбрасывать дополнительное пространство перед каждой не первой строкой)n::#W
вычисляет длину W и сохраняет как глобальное nu::?W
вычисляет уникальные символы в W и сохраняет как глобальныйu?S
генерирует characted-класс для каждого символа SСоставьте таблицу переходов T с одной строкой на уникальный символ в W (плюс один дополнительный) и столбцом для каждого индекса в W (плюс один дополнительный). Дополнительная строка соответствует исходному состоянию, а дополнительный столбец собирает любой символ в S, но не в W. Эта стратегия минимизирует размер таблицы
p:{$[n<#x;0;x~(#x)#W;#x;0]}
это функция, которая ищет самый длинный префиксf:{{|/p'x}'((1_)\x#W),\:/:u}
это функция, которая вычисляет строку х ТПоиск текста с использованием таблицы переходов.
T\[0;u?S]
выполняет итерации по 0 (начальное состояние) и каждому символьному классу S, используя в качестве нового значения значение в транзитной таблице T [state] [charClass]. Конечные состояния имеют значение n, поэтому мы ищем это значение в последовательности состояний и возвращаем его скорректированное (чтобы указать начальную, а не конечную позицию каждого совпадения)источник
Бойер-Мур, Perl (50)
Perl пытается использовать Бойера-Мура естественным образом:
источник