Алгоритм Кнута - Морріса - Пратта  h2>
 Реферат  p>
 Алгоритм Кнута-Моріса-Пратта (КМП) одержує на вхід слово  p>
 X = x [1] x [2] ... x [n]  p>
 і переглядає його зліва направо буква за буквою, заповнюючи при
це масив натуральних чисел l [1] ... l [n], де  p>
 l [i] = длина слова l (x [1] ... х [i])  p>
 (функція l визначена в попередньому пункті). Словами: l [i] є
довжина найбільшого початку слова x [1] ... x [i], одночасно є його
кінцем.  p>
 Яке відношення все це має до пошуку подслова?  p>
 Іншими словами, як використовувати алгоритм КМП для визначення
того, чи є слово A подсловом слова B?  p>
 Рішення. Застосуємо алгоритм КМП до слова A # B, де # - спеціальна
буква, не зустрічається ні в A, ні в B. Слово A є подсловом слова B
тоді і тільки тоді, коли серед чисел в масиві l буде число, яке дорівнює довжині
слова A.  p>
 Описати алгоритм заповнення таблиці l [1] ... l [n].  p>
 Рішення. Припустимо, що перший i значень l [1] ... l [i] вже
знайдені. Ми читаємо чергову літеру слова (тобто x [i +1]) і повинні обчислити
l [i +1].  p>
  p>
  p>
 Іншими словами, нас цікавлять початку Z слова  p>
 x [1] ... x [i +1,  p>
 що одночасно є його кінцями-з них нам треба брати саме
довге. Звідки беруться ці початку? Кожне з них (не рахуючи порожнього)
виходить з деякого слова Z 'приписуванням букви x [i +1]. Слово Z '
є початком і  p>
 кінцем слова x [1] ... x [i]. Однак не будь-яке слово, яке є
початком і кінцем слова x [1] ... x [i], годиться - треба, щоб за ним слідувала
буква x [i +1].  p>
 Отримуємо такий рецепт відшукання слова Z. Розглянемо всі початку
слова x [1] ... x [i], що є одночасно його кінцями. З них виберемо
підходящі - ті, за якими йде буква x [i +1]. З відповідних виберемо саме
довге. Приписавши в його кінець х [i +1], отримаємо шукане слово Z. Тепер пора
скористатися зробленими нами приготуваннями і згадати, що всі слова,
що є одночасно початками і кінцями даного слова, можна отримати
повторними застосуваннями до нього функції l з попереднього розділу.  p>
 Ось що виходить:  p>
 i: = 1; 1 [1]: = 0;  p>
 (таблиця l [1] .. l [i] заповнена правильно)  p>
 while i n do begin  p>
 len: = l [i]  p>
 (len - довжина початку слова x [1] .. x [i], яке є  p>
 його кінцем; дедалі довші початку виявилися  p>
 невідповідними)  p>
 while (x [len +1] х [i +1]) and (len> 0) do begin  p>
 (початок не підходить, застосовуємо до нього функцію l)  p>
 len: = l [len];  p>
 end;  p>
 (знайшли підходяще або переконалися у відсутності)  p>
 if x [len +1] = x [i +1] do begin  p>
 (х [1] .. x [len] - найдовше підходяще початок)  p>
 l [i +1]: = len +1;  p>
 end else begin  p>
 (відповідних немає)  p>
 l [i +1]: = 0;  p>
 end;  p>
 i: = i +1;  p>
 end;  p>
 Довести, що число дій у наведеному тільки що алгоритм не
перевершує Cn для деякої константи C.  p>
 Рішення. Це не цілком очевидно: обробка кожної чергової букви
може зажадати багатьох ітерацій у внутрішньому циклі. Однак кожна така
ітерація зменшує len принаймні на 1, і в цьому випадку l [i +1] виявиться
помітно менше l [i]. З іншого боку, при збільшенні i на одиницю величина
l [i] може зрости не більше ніж на 1, так що часто і сильно спадати вона не
може - інакше спадання не буде скомпенсовано зростанням.  p>
 Більш точно, можна записати нерівність  p>
 l [i +1]