<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=188.170.74.10&amp;*</id>
		<title>Викиконспекты - Вклад участника [ru]</title>
		<link rel="self" type="application/atom+xml" href="http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=188.170.74.10&amp;*"/>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/188.170.74.10"/>
		<updated>2026-06-11T06:57:10Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%B2%D1%82%D0%BE%D0%BC%D0%B0%D1%82_%D0%9A%D0%BD%D1%83%D1%82%D0%B0-%D0%9C%D0%BE%D1%80%D1%80%D0%B8%D1%81%D0%B0-%D0%9F%D1%80%D0%B0%D1%82%D1%82%D0%B0&amp;diff=66179</id>
		<title>Автомат Кнута-Морриса-Пратта</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%B2%D1%82%D0%BE%D0%BC%D0%B0%D1%82_%D0%9A%D0%BD%D1%83%D1%82%D0%B0-%D0%9C%D0%BE%D1%80%D1%80%D0%B8%D1%81%D0%B0-%D0%9F%D1%80%D0%B0%D1%82%D1%82%D0%B0&amp;diff=66179"/>
				<updated>2018-06-27T22:29:31Z</updated>
		
		<summary type="html">&lt;p&gt;188.170.74.10: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Детерминированные_конечные_автоматы|Автомат]] Кнута-Морриса-Пратта используется в алгоритмах, связанных с поиском образца в тексте, в том числе в реальном времени.&lt;br /&gt;
&lt;br /&gt;
== Суффикс-функция ==&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|id = suffix_func&lt;br /&gt;
|definition = Для строки &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; длиной &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; функция &amp;lt;tex&amp;gt; \sigma_p \colon \Sigma^* \to \left\{1,2, \dots ,m\right\}&amp;lt;/tex&amp;gt; называется '''суффикс-функцией''', если она сопоставляет любой строке &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, состоящей из символов алфавита &amp;lt;tex&amp;gt;\Sigma&amp;lt;/tex&amp;gt;, длину максимального суффикса &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, являющегося префиксом &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
==== Пример суффикс-функции ====&lt;br /&gt;
&lt;br /&gt;
Пусть строка &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt;=&amp;quot;&amp;lt;tex&amp;gt;abaab&amp;lt;/tex&amp;gt;&amp;quot;. Вот несколько примеров значений суффикс-функции для нее.&lt;br /&gt;
&lt;br /&gt;
;*&amp;lt;tex&amp;gt;\sigma_p(&amp;quot;aba&amp;quot;)=3&amp;lt;/tex&amp;gt;. &lt;br /&gt;
:В данном случае вся строка является префиксом &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt;.&lt;br /&gt;
;*&amp;lt;tex&amp;gt;\sigma_p(&amp;quot;bb&amp;quot;)=0&amp;lt;/tex&amp;gt;. &lt;br /&gt;
:В данном случае какой бы суффикс мы ни взяли, ни один из них не является префиксом &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt;.&lt;br /&gt;
;*&amp;lt;tex&amp;gt;\sigma_p(&amp;quot;aaab&amp;quot;)=2&amp;lt;/tex&amp;gt;. &lt;br /&gt;
:В данном случае &amp;quot;&amp;lt;tex&amp;gt;ab&amp;lt;/tex&amp;gt;&amp;quot; является префиксом &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt;, а все суффиксы длиннее {{---}} нет.&lt;br /&gt;
&lt;br /&gt;
== Структура автомата ==&lt;br /&gt;
&lt;br /&gt;
[[Детерминированные_конечные_автоматы|Автомат]] строится на строке-образце &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; длины &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;, которую в будущем мы будем искать в тексте. &lt;br /&gt;
&lt;br /&gt;
Для [[Детерминированные_конечные_автоматы|автомата]] Кнута-Морриса-Пратта:&lt;br /&gt;
* &amp;lt;tex&amp;gt;Q = \left\{0,1,...,m\right\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
* &amp;lt;tex&amp;gt; s = 0 &amp;lt;/tex&amp;gt;&lt;br /&gt;
* &amp;lt;tex&amp;gt; T = \left\{m\right\} &amp;lt;/tex&amp;gt;&lt;br /&gt;
* &amp;lt;tex&amp;gt; \delta(q, a) = \sigma_p(p[1 \dots q] + a) &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; {{---}} это состояние, &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; {{---}} символ, по которому осуществляется переход, a &amp;quot;&amp;lt;tex&amp;gt;+&amp;lt;/tex&amp;gt;&amp;quot; {{---}} операция конкатенации (&amp;lt;tex&amp;gt;p[1, 0] = \varepsilon &amp;lt;/tex&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Таким образом, если часть текста, в котором мы ищем образец, уже пропущена через [[Детерминированные_конечные_автоматы|автомат]], то текущее состояние отражает, сколько последних символов этой прочитанной части совпадает с началом нашего образца. Если мы пришли в допускающее состояние, значит последние &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; символов полностью совпадают с образцом и мы нашли включение.&lt;br /&gt;
&lt;br /&gt;
Заметим, что тот факт, что переход по символу осуществляется независимо от последующих, позволяет нам работать как с текстом, данным заранее, так и с текстом, который вводится в реальном времени.&lt;br /&gt;
&lt;br /&gt;
==== Пример автомата Кнута-Морриса-Пратта ====&lt;br /&gt;
[[Файл:Kmp_aut_ex.png‎]]&lt;br /&gt;
&lt;br /&gt;
Данный автомат построен для образца &amp;quot;&amp;lt;tex&amp;gt;abaab&amp;lt;/tex&amp;gt;&amp;quot; и алфавита &amp;lt;tex&amp;gt;\Sigma =\left\{a, b\right\} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Построение автомата ==&lt;br /&gt;
&lt;br /&gt;
=== Идея алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для каждого состояния и каждого символа будем определять значение функции перехода из данного состояния по данному символу. Пусть текущее состояние &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt;. При считывании каждого нового символа &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; из текста возможно два варианта развития событий:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;''Символ &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; совпадает с &amp;lt;tex&amp;gt;q + 1&amp;lt;/tex&amp;gt; символом строки &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt;.''&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Это значит, что число последних символов текста, совпадающих с началом образца увеличилось на 1. Значит переход осуществляется в следующее состояние. В этом случае &amp;lt;tex&amp;gt;\delta(q, a) = q + 1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;''Символ &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; не совпадает с &amp;lt;tex&amp;gt;q + 1&amp;lt;/tex&amp;gt; символом строки &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt;.''&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Тогда заметим, что если к строке, являющейся максимальным [[Основные_определения,_связанные_со_строками#border|бордером]] предыдущего совпадения, добавить прочитанный символ, то как раз получится текущее окончание текста, совпадающее с началом образца. Таким образом, в этом случае &amp;lt;tex&amp;gt;\delta(q, a) = \delta(\pi_p(q), a)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\pi_p(q)&amp;lt;/tex&amp;gt; {{---}} [[Префикс-функция|префикс-функция]] для строки &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt;. Исключением для этого случая является лишь нулевое состояние. Если считанный символ не совпадает с первым символом образца, то мы останемся в нулевом состоянии, так как по прежнему совпадением является пустая строка.&lt;br /&gt;
&lt;br /&gt;
=== Асимптотика ===&lt;br /&gt;
&lt;br /&gt;
В данном алгоритме нам нужно лишь вычислить значение функции перехода в каждом состоянии для каждого символа. При предподсчитанной за &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; префикс-функции вычисление для одного состояния и одного символа происходит за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;. Всего состояний &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;, а символов &amp;lt;tex&amp;gt;|\Sigma|&amp;lt;/tex&amp;gt;. Итого &amp;lt;tex&amp;gt;O(m + m \cdot |\Sigma|)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Псевдокод ===&lt;br /&gt;
&lt;br /&gt;
 '''function''' make_kmp()&lt;br /&gt;
   '''for''' q = 0 '''to''' m&lt;br /&gt;
     '''for''' a &amp;lt;tex&amp;gt;\in \Sigma&amp;lt;/tex&amp;gt;&lt;br /&gt;
       '''if''' q &amp;gt; 0 '''and''' a &amp;lt;tex&amp;gt;\ne&amp;lt;/tex&amp;gt; p[q + 1]&lt;br /&gt;
         &amp;lt;tex&amp;gt;\delta&amp;lt;/tex&amp;gt;(q, a) = &amp;lt;tex&amp;gt;\delta&amp;lt;/tex&amp;gt;(&amp;lt;tex&amp;gt;\pi_p&amp;lt;/tex&amp;gt;(q), a)&lt;br /&gt;
       '''if''' a = p[q + 1]&lt;br /&gt;
         &amp;lt;tex&amp;gt;\delta&amp;lt;/tex&amp;gt;(q, a) = q + 1&lt;br /&gt;
       '''else'''&lt;br /&gt;
         &amp;lt;tex&amp;gt;\delta&amp;lt;/tex&amp;gt;(q, a) = q&lt;br /&gt;
&lt;br /&gt;
== Сравнение с другими алгоритмами поиска образца в тексте ==&lt;br /&gt;
&lt;br /&gt;
При решении задачи поиска всех включений образца в текст также часто применяются алгоритмы Ахо-Корасик и Кнута-Морриса-Пратта.&lt;br /&gt;
&lt;br /&gt;
Алгоритм Ахо-Корасик использует автомат, построенный на основе приведенного здесь, и является расширением рассматриваемого алгоритма. Он применяется в несколько иных случаях {{---}} когда образцов для поиска несколько. И решает эту задачу быстрее, чем построение нескольких автоматов Кнута-Морриса-Пратта.&lt;br /&gt;
&lt;br /&gt;
Алгоритм Кнута-Морриса-Пратта решает ту же задачу, что и алгоритм с применением одноименного автомата. Однако он не может работать с текстом, вводимым в режиме реального времени, ему нужно заранее знать текст, в котором нужно искать образец. Также, если текст достаточно объемный, алгоритм Кнута-Морриса-Пратта будет использовать гораздо больше памяти, чем приведенный выше в данной статье. Однако, если текст небольшой и дан заранее, алгоритм Кнута-Морриса-Пратта будет работать быстрее.&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
*[[Алгоритм Ахо-Корасик]]&lt;br /&gt;
*[[Алгоритм Кнута-Морриса-Пратта]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
*[[wikipedia:Finite-state_machine|Wikipedia {{---}} Finite-state machine]]&lt;br /&gt;
*ISBN 978-5-8459-1794-2 '''Томас Кормен, Чарльз Лейзерсон, Рональд Ривест, Клиффорд Штайн''' {{---}} Алгоритмы. Построение и анализ, стр. 771{{---}}776.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Поиск подстроки в строке]]&lt;br /&gt;
[[Категория: Автоматы и регулярные языки]]&lt;br /&gt;
[[Категория:Точный поиск]]&lt;/div&gt;</summary>
		<author><name>188.170.74.10</name></author>	</entry>

	</feed>