Алгоритм Кнута-Морріса-Пратта
Це завдання є класичним прикладом застосування префікс-функції (і, власне, вона була відкрита саме у зв'язку з цим).
Дано текст та рядок . Потрібно знайти та вивести всі позиції входження рядка у текст .
Алгоритм
Позначимо для зручності через довжину рядка , а через — довжину тексту .
Утворимо рядок , де символ — це роздільник, який не повинен зустрічатися ніде більше. Обчислимо для цього рядка префікс-функцію. Тепер розглянемо її значення, окрім перших (які, як видно, належать до рядка і роздільника). За визначенням, значення показує найдовшу довжину підрядка, що закінчується в позиції і збігається з префіксом. Але у нашому випадку це — фактично довжина найбільшого блоку збігу з рядком , що закінчується в позиції . Більшою за ця довжина бути не може — завдяки роздільнику. А от рівність (там, де вона досягається), означає, що в позиції закінчується шукане входження рядка (тільки не треба забувати, що всі позиції відлічуються у склеєному рядку ).
Таким чином, якщо в деякій позиції виявилося , то в позиції рядка починається наступне входження рядка у рядок .
Як уже згадувалося при описі алгоритму обчислення префікс-функції, якщо відомо, що значення префікс-функції не перевищуватимуть деякої величини, то достатньо зберігати не весь рядок і префікс-функцію, а лише її початок. У нашому випадку це означає, що потрібно зберігати в пам'яті лише рядок та значення префікс-функції на ньому, а потім уже зчитувати по одному символу рядок і перераховувати поточне значення префікс-функції.
Отже, алгоритм Кнута-Морріса-Пратта вирішує це завдання за часу та пам'яті.
Реалізація
TODO: add implementation.
Застосування
TODO: add applications.
Задачі
TODO: add problems.