<?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=217.197.6.98&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=217.197.6.98&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/217.197.6.98"/>
		<updated>2026-06-11T14:09:21Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D0%B5%D0%BE%D1%80%D0%B5%D1%82%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8%D0%B9_%D0%BC%D0%B8%D0%BD%D0%B8%D0%BC%D1%83%D0%BC_%D0%BF%D0%BE_%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%BC%D1%83_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D1%83_%D0%B7%D0%B0_6_%D1%81%D0%B5%D0%BC%D0%B5%D1%81%D1%82%D1%80&amp;diff=48776</id>
		<title>Теоретический минимум по функциональному анализу за 6 семестр</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D0%B5%D0%BE%D1%80%D0%B5%D1%82%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8%D0%B9_%D0%BC%D0%B8%D0%BD%D0%B8%D0%BC%D1%83%D0%BC_%D0%BF%D0%BE_%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%BC%D1%83_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D1%83_%D0%B7%D0%B0_6_%D1%81%D0%B5%D0%BC%D0%B5%D1%81%D1%82%D1%80&amp;diff=48776"/>
				<updated>2015-06-23T13:31:20Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: /* 26 Теорема Шаудера о неподвижной точке */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== 1 A* и его ограниченность ==&lt;br /&gt;
Пусть оператор &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt; действует из &amp;lt;tex&amp;gt; E &amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt; F &amp;lt;/tex&amp;gt;, и функционал &amp;lt;tex&amp;gt; \varphi &amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt; F^* &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим &amp;lt;tex&amp;gt; f(x) = \varphi (Ax), | f(x) | \le \| \varphi \| \| A \| \| x \| &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получили новый функционал &amp;lt;tex&amp;gt; f &amp;lt;/tex&amp;gt;, принадлежащий &amp;lt;tex&amp;gt; E^* &amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt; \varphi \mapsto \varphi A &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \varphi A = A^* (\varphi), A^* : F^* \to E^* &amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt; A^* &amp;lt;/tex&amp;gt; {{---}} '''сопряженный оператор''' к &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt; {{---}} линейный ограниченный оператор, то &amp;lt;tex&amp;gt; \| A^* \| = \| A \| &amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== 2 Ортогональные дополнения &amp;lt;tex&amp;gt; E &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; E^* &amp;lt;/tex&amp;gt; ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt; E &amp;lt;/tex&amp;gt; {{---}} НП, &amp;lt;tex&amp;gt; S \subset E^* &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; S^{\bot} = \{ x \in E \mid \forall f \in S: f(x) = 0 \} &amp;lt;/tex&amp;gt; {{---}} '''ортогональное дополнение''' &amp;lt;tex&amp;gt; S &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Аналогично, если &amp;lt;tex&amp;gt; T \subset E &amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt; T^{\bot} = \{ f \in E^* \mid \forall x \in T: f(x) = 0 \} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement= &amp;lt;tex&amp;gt; \{ 0 \} = (E^*)^{\bot}, \{ \mathbf{0} \} = E^{\bot} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== 3 Ортогональное дополнение R(A) ==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement= &amp;lt;tex&amp;gt; A \in \mathcal{L}(E,F) \implies \operatorname{Cl} R(A) = (\operatorname{Ker} A^*)^\perp &amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== 4 Ортогональное дополнение R(A*) ==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement= &amp;lt;tex&amp;gt; A \in \mathcal{L}(E,F),~R(A) = \operatorname{Cl} R(A) \implies  R(A^*) = (\operatorname{Ker}A )^\perp &amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== 5 Арифметика компактных операторов ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
Множество называется '''относительно компактным (предкомпактным)''', если его замыкание компактно&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
Линейный ограниченный оператор &amp;lt;tex&amp;gt; A : X \to Y &amp;lt;/tex&amp;gt; называется '''компактным''', если &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt; переводит любое ограниченное подмножество &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; в относительно компактное множество из &amp;lt;tex&amp;gt; Y &amp;lt;/tex&amp;gt;. &lt;br /&gt;
}}&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement = &lt;br /&gt;
&amp;lt;tex&amp;gt; A \in \mathcal{L} (X,Y), ~ B \in \mathcal{L} (Y,Z) &amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; C = B \cdot A &amp;lt;/tex&amp;gt; (произведение, суперпозиция). Тогда:&lt;br /&gt;
&lt;br /&gt;
# Если &amp;lt;tex&amp;gt; B &amp;lt;/tex&amp;gt; ­— ограниченный, &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt; ­— компактный, то &amp;lt;tex&amp;gt; C &amp;lt;/tex&amp;gt; ­— компактный.&lt;br /&gt;
# Если &amp;lt;tex&amp;gt; B &amp;lt;/tex&amp;gt; ­— компактный, &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt; ­— ограниченный, то &amp;lt;tex&amp;gt; C &amp;lt;/tex&amp;gt; ­— компактный.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== 9 Размерность Ker(I-A) компактного A ==&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; {{---}} компактный оператор. Тогда &amp;lt;tex&amp;gt;\dim\operatorname{Ker}(I-A) &amp;lt; + \infty&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== 10 Замкнутость R(I-A)  компактного A ==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;T = I - A&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; компактен, тогда &amp;lt;tex&amp;gt; R(T) &amp;lt;/tex&amp;gt; замкнуто.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== 11 Лемма о Ker(I-A)^n  компактного A ==&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement=&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt; M_n = \operatorname{Ker} ((I - A)^n), n \in \mathbb N&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt; — компактный оператор.&lt;br /&gt;
Тогда &amp;lt;tex&amp;gt; \exists n_0: M_{n_0} = M_{n_0 + 1} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== 12 Условие справедливости  равенства  R(I-A)=E ==&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement=&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt; — компактный оператор на банаховом &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; T = I - A &amp;lt;/tex&amp;gt;.&lt;br /&gt;
Тогда &amp;lt;tex&amp;gt; R(T) = X \iff \operatorname{Ker} T = \{0\} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== 13 Альтернатива Фредгольма-Шаудера ==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|about=&lt;br /&gt;
альтернатива Фредгольма-Шаудера&lt;br /&gt;
|statement=&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;A:X \to X&amp;lt;/tex&amp;gt; — компактный оператор и &amp;lt;tex&amp;gt;T = A - \lambda I&amp;lt;/tex&amp;gt;. Тогда возможно только две ситуации:&lt;br /&gt;
# &amp;lt;tex&amp;gt;\operatorname{Ker} T = \{0\}&amp;lt;/tex&amp;gt;, тогда &amp;lt;tex&amp;gt; y = Tx&amp;lt;/tex&amp;gt; разрешимо для любого &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt;&lt;br /&gt;
# &amp;lt;tex&amp;gt;\operatorname{Ker} T \ne \{0\}&amp;lt;/tex&amp;gt;, тогда &amp;lt;tex&amp;gt; y = Tx&amp;lt;/tex&amp;gt; разрешимо только для тех &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt;, которые принадлежат &amp;lt;tex&amp;gt;(\operatorname{Ker} T^*)^\perp&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== 14 Спектр компактного оператора ==&lt;br /&gt;
Рассмотрим &amp;lt;tex&amp;gt;A - \lambda I&amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
# &amp;lt;tex&amp;gt;\operatorname{Ker} (A - \lambda I) \ne \{0\}&amp;lt;/tex&amp;gt;, тогда оператор необратим, и &amp;lt;tex&amp;gt;\lambda&amp;lt;/tex&amp;gt; — собственное число, то есть &amp;lt;tex&amp;gt;\lambda \in \sigma(A)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# &amp;lt;tex&amp;gt;\operatorname{Ker} (A - \lambda I) = \{0\}&amp;lt;/tex&amp;gt;, тогда по альтернативе, оператор непрерывно обратим, то есть &amp;lt;tex&amp;gt;\lambda \in \rho(A)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Таким образом, спектр состоит из собственных чисел, и, возможно, нуля. Теперь изучим мощность спектра:&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
Спектр компактного оператора не более чем счётен и его предельной точкой может быть только 0.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== 15 Определение самосопряженного оператора, неравенство для (a+ib)(I-A) ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Оператор &amp;lt;tex&amp;gt;\mathcal{A}&amp;lt;/tex&amp;gt; называется ''самосопряжённым'' (&amp;lt;tex&amp;gt;\mathcal{A} = \mathcal{A}^*&amp;lt;/tex&amp;gt;), если &amp;lt;tex&amp;gt;\forall x, y : \langle \mathcal{A}x, y \rangle = \langle x, \mathcal{A}y \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;tex&amp;gt;\lambda \in \mathbb{C}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\lambda \mathcal{I} - \mathcal{A} = (\mu\mathcal{I} - \mathcal{A}) + i\nu\mathcal{I}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\|(\lambda\mathcal{I}-\mathcal{A})x\| \ge |\nu|\cdot\|x\|&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 16 Вещественность спектра ограниченного самосопряженного оператора ==&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement=Собственные числа самосопряжённого оператора вещественны&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== 17 Критерий включения в резольвентное  множество ограниченного самосопряженного оператора ==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=Пусть &amp;lt;tex&amp;gt;\mathcal{A}&amp;lt;/tex&amp;gt;{{---}} самосопряжённый оператор. Тогда&lt;br /&gt;
&amp;lt;tex&amp;gt;\lambda \in \rho(\mathcal{A}) \iff \exists m &amp;gt; 0 : \forall x \in \mathcal{H} : \|(\lambda\mathcal{I}-\mathcal{A})x\| \ge m\|x\|&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== 18 Критерий включения в спектр  ограниченного самосопряженного оператора ==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=Пусть &amp;lt;tex&amp;gt;\mathcal{A}&amp;lt;/tex&amp;gt;{{---}} самосопряжённый оператор. Тогда&lt;br /&gt;
&amp;lt;tex&amp;gt;\lambda \in \sigma(\mathcal{A}) \iff \exists x_n : \|x_n\| = 1 : \|(\lambda\mathcal{I}-\mathcal{A})x_n\| \to 0 &amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== 19 Локализация спектра с.с. оператора посредством  чисел m- и m+ ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&amp;lt;tex&amp;gt;m_- = \inf\limits_{\|x\| = 1} \langle \mathcal{A}x, x\rangle, m_+ = \sup\limits_{\|x\| = 1} \langle \mathcal{A}x, x \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=Пусть A — самосопряженный оператор&lt;br /&gt;
&lt;br /&gt;
1. &amp;lt;tex&amp;gt;\sigma(\mathcal{A}) \subset [m_-; m_+]&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. &amp;lt;tex&amp;gt;m_+, m_- \in \sigma(\mathcal{A})&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== 20 Спектральный радиус ограниченного самосопряженного оператора и его норма ==&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement=Если &amp;lt;tex&amp;gt;\mathcal{A}&amp;lt;/tex&amp;gt;{{---}} самосопряжённый оператор, то &amp;lt;tex&amp;gt;r_\sigma(\mathcal{A}) = \|\mathcal{A}\|&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== 21 Теорема Гильберта-Шмидта ==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|author=Гильберт, Шмидт&lt;br /&gt;
|statement=Если &amp;lt;tex&amp;gt;\mathcal{A}&amp;lt;/tex&amp;gt;{{---}} самосопряжённый компактный оператор в гильбертовом пространстве &amp;lt;tex&amp;gt;\mathcal{H}&amp;lt;/tex&amp;gt;, а &amp;lt;tex&amp;gt;M_{\lambda_i}&amp;lt;/tex&amp;gt;{{---}} его (оператора) собственные подпространства, то &amp;lt;tex&amp;gt;\mathcal{H} = M_{\lambda_1} \oplus M_{\lambda_2} \oplus \cdots \oplus M_{\lambda_n} \oplus \cdots &amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== 22 Разложение резольвенты компактного  самосопряженного оператора. ==&lt;br /&gt;
&amp;lt;tex&amp;gt;R_\lambda(y) = \sum\limits_{n=1}^\infty \frac{\langle y, \varphi_n\rangle}{\lambda-\lambda_n}\varphi_n&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Теорема Банаха о сжимающем отображении==&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Пусть на замкнутом шаре &amp;lt;tex&amp;gt;\overline{V} \subset X&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; - метрическое пространство, определён оператор &amp;lt;tex&amp;gt;A: \overline{V} \subset X \to X&amp;lt;/tex&amp;gt;. Он называется '''сжатием''' на &amp;lt;tex&amp;gt;\overline{V}&amp;lt;/tex&amp;gt;, если &amp;lt;tex&amp;gt;\exists\alpha\in(0; 1)&amp;lt;/tex&amp;gt; такой, что для &amp;lt;tex&amp;gt;{\forall}x,y \in M&amp;lt;/tex&amp;gt; выполняется &amp;lt;tex&amp;gt;{\rho(Ax,Ay)\leqslant\alpha{\cdot}\rho(x,y)}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=(''Банаха о неподвижной точке'')&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;T : \overline{V} \to \overline{V}&amp;lt;/tex&amp;gt; и является сжатием, тогда в этом шаре у оператора &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\exists !&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;T : V_r(x_0) \to Y&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;V_r(x_0) \subset X&amp;lt;/tex&amp;gt; и, кроме того, &amp;lt;tex&amp;gt;X, Y&amp;lt;/tex&amp;gt; - нормированные пространства.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;\|\delta x \| &amp;lt; r&amp;lt;/tex&amp;gt;. Тогда, очевидно, &amp;lt;tex&amp;gt;x + \delta x \in V_r(x_0)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Обозначим &amp;lt;tex&amp;gt;\delta T(x_0, \delta x) = T(x_0 + \delta x) - T(x_0)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Def.''' Отображение &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; называется дифференцируемым по Фреше в точке &amp;lt;tex&amp;gt;x_0&amp;lt;/tex&amp;gt;, если существует оператор &amp;lt;tex&amp;gt;A_{x_0} \in L(X,Y)&amp;lt;/tex&amp;gt; такой, что &amp;lt;tex&amp;gt;\delta T(x_0, \delta x) = A_{x_0}(\delta x) + o(\delta x)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;o(\delta x)&amp;lt;/tex&amp;gt; несёт следующий смысл: &amp;lt;tex&amp;gt;\frac{ {\|o(\delta x)\|}_Y } {{\| \delta x \|}_X} \to 0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Обычно, в случае дифференцируемого отображения используют следующее обозначение: &amp;lt;tex&amp;gt;T_{x_0}' = A_{x_0}&amp;lt;/tex&amp;gt;. Подчеркнем, что &amp;lt;tex&amp;gt;T_{x_0}': X \to Y&amp;lt;/tex&amp;gt;. Аргументом является &amp;quot;отклонение&amp;quot; некоторой точки &amp;lt;tex&amp;gt;x'&amp;lt;/tex&amp;gt; от &amp;lt;tex&amp;gt;x_0&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;x - x_0&amp;lt;/tex&amp;gt;. А результат применения оператора: &amp;lt;tex&amp;gt;T(x') - T(x_0)&amp;lt;/tex&amp;gt; с точностью до &amp;lt;tex&amp;gt;o(\delta x = x' - x)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Lm.''' (''Неравенство Лагранжа'')&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;X, Y&amp;lt;/tex&amp;gt; -- нормированные пространства, &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt; -- некоторый шар в &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; и дан оператор &amp;lt;tex&amp;gt;T : V \to Y&amp;lt;/tex&amp;gt; и на всем этом шаре &amp;lt;tex&amp;gt;\exists T'(x)&amp;lt;/tex&amp;gt;. Тогда для любых &amp;lt;tex&amp;gt;a, b \in V : \|T(b) - T(a)\| \le M {\|b - a\|}_X&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;M = sup_{x \in [a, b]}\|T'(x)\|&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Локальная теорема о неявном отображении==&lt;br /&gt;
&lt;br /&gt;
'''Th.'''(''о неявном отображении'')&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt; - шар в &amp;lt;tex&amp;gt; X, V \subset X&amp;lt;/tex&amp;gt;, а &amp;lt;tex&amp;gt;W \subset Y&amp;lt;/tex&amp;gt; - шар в &amp;lt;tex&amp;gt;Y&amp;lt;/tex&amp;gt;, и задан оператор &amp;lt;tex&amp;gt;T : {V} \times {W} \rightarrow Y&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;x_0 \in V,\: y_0 \in W,\: T(x_0, y_0) = 0 \in Y&amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt; \forall x \in V, \forall y \in W \quad \exists T^{'}_y &amp;lt;/tex&amp;gt; - дифференциал Фреше, непрерывный как отображение переменных &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть также &amp;lt;tex&amp;gt;T^{'}_{y}(x_0, y_0)&amp;lt;/tex&amp;gt; - непрерывно обратим.&lt;br /&gt;
&lt;br /&gt;
'''Тогда''' задача о неявном отображении для &amp;lt;tex&amp;gt;T(x, y) = 0&amp;lt;/tex&amp;gt; c начальным решением &amp;lt;tex&amp;gt;T(x_0, y_0) = 0&amp;lt;/tex&amp;gt; разрешима в некоторых окрестностях точек &amp;lt;tex&amp;gt;x_0, y_0&amp;lt;/tex&amp;gt;, а именно: для любого &amp;lt;tex&amp;gt;x' \in V_{\delta_1}(x_0)&amp;lt;/tex&amp;gt; существует единственное &amp;lt;tex&amp;gt;y' \in V_{\delta_2}(y_0) : T(x', y') = 0&amp;lt;/tex&amp;gt; .&lt;br /&gt;
&lt;br /&gt;
http://neerc.ifmo.ru/wiki/index.php?title=Локальная_теорема_о_неявном_отображении&lt;br /&gt;
&lt;br /&gt;
== 24 Локальная сходимость метода Ньютона для операторных уравнений ==&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathcal{F}(x) = x - \Gamma(x) \mathcal{T} (x)&amp;lt;/tex&amp;gt;&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement=&amp;lt;tex&amp;gt; \mathcal{F}'(\overline x) = 0 &amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== 25 Проекторы Шаудера ==&lt;br /&gt;
&amp;lt;tex&amp;gt; \forall \varepsilon &amp;gt; 0 \exists y_1 \in M, \hdots, y_p \in M &amp;lt;/tex&amp;gt; {{---}} конечная &amp;lt;tex&amp;gt; \varepsilon &amp;lt;/tex&amp;gt;-сеть.&lt;br /&gt;
&lt;br /&gt;
Построим следующую функцию: &amp;lt;tex&amp;gt; \forall j = 1, \hdots, p, \forall y \in M: &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \mu_j(y) = \begin{cases} &lt;br /&gt;
0                           &amp;amp; \mbox{if } \| y - y_j \| \ge \varepsilon \\&lt;br /&gt;
\varepsilon - \| y - y_j \| &amp;amp; \mbox{if } \| y - y_j \| &amp;lt; \varepsilon \end{cases} &lt;br /&gt;
&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; S(y) = \sum\limits_{j=1}^p \mu_j(y) &amp;lt;/tex&amp;gt;&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex dpi = 140&amp;gt; P_\varepsilon (y) = \sum\limits_{j=1}^p \frac {\mu_j(y)} {S(y)} y_j &amp;lt;/tex&amp;gt; {{---}} ''проектор Шаудера''.&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== 26 Теорема Шаудера о неподвижной точке ==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|author=Шаудер&lt;br /&gt;
|about=о неподвижной точке&lt;br /&gt;
|statement=&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt; M &amp;lt;/tex&amp;gt; {{---}} ограниченное замкнутое выпуклое подмножество B-пространства &amp;lt;tex&amp;gt; X &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; \mathcal{T} &amp;lt;/tex&amp;gt; вполне непрерывно отображает &amp;lt;tex&amp;gt; M &amp;lt;/tex&amp;gt; в себя. &lt;br /&gt;
&lt;br /&gt;
Тогда &amp;lt;tex&amp;gt; \exists x^* \in M : x^* = Tx^* &amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== 6 О компактности A*, сепарабельность R(A) ==&lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement = &lt;br /&gt;
Пусть &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt; ­— компактный, тогда &amp;lt;tex&amp;gt; R(A) &amp;lt;/tex&amp;gt; — сепарабельно (то есть, в &amp;lt;tex&amp;gt; R(A) &amp;lt;/tex&amp;gt; существует счетное всюду плотное подмножество).&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement = &lt;br /&gt;
&amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; — компактен &amp;lt;tex&amp;gt;\implies&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;A^*&amp;lt;/tex&amp;gt; — компактен&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== 7 Базис Шаудера, лемма о координатном пространстве ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=&lt;br /&gt;
Базисом Шаудера в банаховом пространстве &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; называется множество его элементов &amp;lt;tex&amp;gt;e_1, e_2 \dots e_n \dots&amp;lt;/tex&amp;gt; такое, что у любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; существует единственное разложение &amp;lt;tex&amp;gt;x = \sum\limits_{i = 1}^{\infty} \alpha_i e_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Определим &amp;lt;tex&amp;gt;F = \{(\alpha_1 \dots \alpha_n\dots) \mid \exists x \in X: \sum\limits_{n=1}^\infty \alpha_n e_n \to x \}&amp;lt;/tex&amp;gt; — это линейное пространство. &lt;br /&gt;
&lt;br /&gt;
Так как ряд сходится, &amp;lt;tex&amp;gt;F&amp;lt;/tex&amp;gt; можно превратить в НП, определив норму как &amp;lt;tex&amp;gt;\| \alpha \| = \sup\limits_n \left\| \sum\limits_{i=1}^n \alpha_i e_i\right\|&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement=&lt;br /&gt;
Пространство &amp;lt;tex&amp;gt; F &amp;lt;/tex&amp;gt; относительно этой нормы — банахово.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== 8 Почти конечномерность компактного оператора ==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|about=&lt;br /&gt;
почти конечномерность компактного оператора&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; — банахово пространство с базисом Шаудера, &amp;lt;tex&amp;gt;A:X \to X&amp;lt;/tex&amp;gt; — компактный, то для всех &amp;lt;tex&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/tex&amp;gt; существует разложение оператора &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; в сумму двух компактных операторов: &amp;lt;tex&amp;gt;A = A_1 + A_2&amp;lt;/tex&amp;gt; такое, что:&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;tex&amp;gt;\operatorname{dim}(R(A_1)) &amp;lt; +\infty&amp;lt;/tex&amp;gt;&lt;br /&gt;
# &amp;lt;tex&amp;gt;\|A_2\| &amp;lt; \varepsilon&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
== 23 Локальная сходимость метода простой итерации ==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|about=Локальная теорема о простой итерации&lt;br /&gt;
|statement=&lt;br /&gt;
Пусть известно, что существует &amp;lt;tex&amp;gt; \overline{x}: \mathcal{T}(\overline{x}) = \overline{x} &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; \| \mathcal{T}(\overline{x})' \| \le q &amp;lt; 1 &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Тогда существует такой шар &amp;lt;tex&amp;gt; V_{\delta} (\overline x) &amp;lt;/tex&amp;gt;, что если &amp;lt;tex&amp;gt; x_0 \in V_{\delta} (\overline x) &amp;lt;/tex&amp;gt;, то:&lt;br /&gt;
* Метод простых итераций корректно определен: &amp;lt;tex&amp;gt; \mathcal{T}x_n \in V_{\delta} (\overline x), n \ge 0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* &amp;lt;tex&amp;gt; x_n \to \overline x &amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Функциональный анализ 3 курс]]&lt;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE_%D0%9D%D0%9A%D0%90_%D1%8D%D0%BA%D0%B2%D0%B8%D0%B2%D0%B0%D0%BB%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%94%D0%9A%D0%90,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A2%D0%BE%D0%BC%D0%BF%D1%81%D0%BE%D0%BD%D0%B0&amp;diff=43471</id>
		<title>Построение по НКА эквивалентного ДКА, алгоритм Томпсона</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE_%D0%9D%D0%9A%D0%90_%D1%8D%D0%BA%D0%B2%D0%B8%D0%B2%D0%B0%D0%BB%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%94%D0%9A%D0%90,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A2%D0%BE%D0%BC%D0%BF%D1%81%D0%BE%D0%BD%D0%B0&amp;diff=43471"/>
				<updated>2015-01-06T08:02:45Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: /* Алгоритм */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Описание ==&lt;br /&gt;
Алгоритм Томпсона строит по [[Недетерминированные конечные автоматы|НКА]] эквивалентный [[Детерминированные конечные автоматы|ДКА]] следующим образом:&lt;br /&gt;
* Начало.&lt;br /&gt;
* '''Шаг 1.''' Помещаем в очередь &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; множество, состоящее только из стартовой вершины.&lt;br /&gt;
* '''Шаг 2.''' Затем, пока очередь не пуста выполняем следующие действия:&lt;br /&gt;
** Достаем из очереди множество, назовем его &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt;&lt;br /&gt;
** Для всех &amp;lt;tex&amp;gt;c \in \Sigma&amp;lt;/tex&amp;gt; посмотрим в какое состояние ведет переход по символу &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; из каждого состояния в &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt;. Полученное множество состояний положим в очередь &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; только если оно не лежало там раньше. Каждое такое множество в итоговом ДКА будет отдельной вершиной, в которую будут вести переходы по соответствующим символам.&lt;br /&gt;
** Если в множестве &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; хотя бы одна из вершин была терминальной в НКА, то соответствующая данному множеству вершина в ДКА также будет терминальной.&lt;br /&gt;
* Конец.&lt;br /&gt;
&lt;br /&gt;
== Построение эквивалентного ДКА по НКА ==&lt;br /&gt;
&lt;br /&gt;
Пусть нам дан произвольный НКА: &amp;lt;tex&amp;gt;\langle \Sigma , Q, s \in Q, T \subset Q, \delta : Q \times \Sigma \to 2^Q \rangle&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Построим по нему следующий ДКА: &amp;lt;tex&amp;gt;\langle \Sigma , Q_d, s_d \in Q_d, T_d \subset Q_d, \delta_d : Q_d \times \Sigma \to Q_d \rangle&amp;lt;/tex&amp;gt;, где:&lt;br /&gt;
# &amp;lt;tex&amp;gt;Q_d = \{q_d \mid q_d \subset 2^Q \}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;s_d = \{s\}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;T_d = \{q \in Q_d \mid \exists p \in T : p \in q\}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;\delta_d(q, c) = \{ \delta(a, c) \mid a \in q \}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Доказательство эквивалентности===&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
Построенный ДКА эквивалентен данному НКА.&lt;br /&gt;
|proof=&lt;br /&gt;
#Докажем, что любое слово, которое принимает НКА, будет принято построенным ДКА. Заметим, что &amp;lt;tex&amp;gt;\forall q \in q_d, \forall c \in \Sigma, \forall p \in \delta(q, c): p \in \delta_d(q_d, c)&amp;lt;/tex&amp;gt;. Рассмотрим слово &amp;lt;tex&amp;gt;w=w_1 \dots w_m&amp;lt;/tex&amp;gt;, которое принимает автомат НКА: &amp;lt;tex&amp;gt;\langle s, w_1w_2 \dots w_m \rangle \vdash \langle u_1, w_2 \dots w_m \rangle \vdash \langle u_m, \varepsilon \rangle, u_m \in T&amp;lt;/tex&amp;gt;. Проверим, что построенный ДКА тоже принимает это слово. Заметим, что &amp;lt;tex&amp;gt;s \in s_d&amp;lt;/tex&amp;gt;, а, значит, исходя из нашего наблюдения, мы получаем, что &amp;lt;tex&amp;gt;u_1 \in {u_d}_1&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;{u_d}_1 = \delta_d(s, w_1)&amp;lt;/tex&amp;gt;. Далее, несложно заметить, что &amp;lt;tex&amp;gt;\forall i \leqslant m : u_i \in {u_d}_i&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\langle s_d, w_1w_2 \dots w_m \rangle \vdash \langle {u_d}_1, w_2 \dots w_m \rangle \vdash \langle {u_d}_i, w_{i + 1} \dots w_m\rangle&amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;tex&amp;gt;u_m \in {u_d}_m&amp;lt;/tex&amp;gt;, а из определения терминальных состояний в построенном ДКА мы получаем, что &amp;lt;tex&amp;gt;{u_d}_m \in T_d&amp;lt;/tex&amp;gt;, то есть наш ДКА тоже принимает cлово &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Докажем, что любое слово, которое принимает построенный ДКА, принимает и НКА. Сначала сделаем наблюдение, что если &amp;lt;tex&amp;gt;q_d=\{q\}&amp;lt;/tex&amp;gt;, и мы из него достигли по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; какого-то состояния &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\forall p \in p_d&amp;lt;/tex&amp;gt; существует путь из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; в НКА по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим слово &amp;lt;tex&amp;gt;w=w_1 \dots w_m&amp;lt;/tex&amp;gt;, которое принимает автомат ДКА: &amp;lt;tex&amp;gt;\langle s_d, w_1w_2 \dots w_m \rangle \vdash \langle {u_d}_1, w_2 \dots w_m \rangle \vdash \langle {u_d}_m, \varepsilon \rangle, {u_d}_m \in T_d&amp;lt;/tex&amp;gt;. Проверим, что НКА тоже принимает это слово. Так как &amp;lt;tex&amp;gt;s_d = \{s\}&amp;lt;/tex&amp;gt;, и мы из &amp;lt;tex&amp;gt;s_d&amp;lt;/tex&amp;gt; достигли &amp;lt;tex&amp;gt;{u_d}_m \in T_d&amp;lt;/tex&amp;gt;, возьмём любое терминальное состояние &amp;lt;tex&amp;gt;u_m \in {u_d}_m&amp;lt;/tex&amp;gt;. По нашему наблюдению в НКА есть путь из &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;u_m&amp;lt;/tex&amp;gt; по строке &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;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;
* &amp;lt;tex&amp;gt;\mathtt{P}&amp;lt;/tex&amp;gt; {{---}} очередь состояний, соответствующих множествам, состоящих из состояний НКА. &lt;br /&gt;
* &amp;lt;tex&amp;gt;\mathtt{Q_d}&amp;lt;/tex&amp;gt; {{---}} массив множеств, соответствующих состояниям ДКА.&lt;br /&gt;
* &amp;lt;tex&amp;gt;\mathtt{s}&amp;lt;/tex&amp;gt; {{---}} стартовое состояние НКА.&lt;br /&gt;
 '''Automaton''' getDFAbyNFA(&amp;lt;tex&amp;gt;\langle \Sigma, Q, s, T, \delta \rangle&amp;lt;/tex&amp;gt; : '''Automaton'''):&lt;br /&gt;
    &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;.push({s})&lt;br /&gt;
    &amp;lt;tex&amp;gt;Q_d&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;\varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''while''' &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt; \neq &amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
       &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;.pop(&amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''for''' &amp;lt;tex&amp;gt;c \in \Sigma&amp;lt;/tex&amp;gt;&lt;br /&gt;
          &amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;\varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
          '''for''' &amp;lt;tex&amp;gt;p \in p_d&amp;lt;/tex&amp;gt;&lt;br /&gt;
             &amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;q_d \cup \{ \delta(p, c) \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
             &amp;lt;tex&amp;gt;\delta_d(p_d, q_d)&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;&lt;br /&gt;
          '''if''' &amp;lt;tex&amp;gt;q_d \notin Q_d&amp;lt;/tex&amp;gt;&lt;br /&gt;
             &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt;)&lt;br /&gt;
             &amp;lt;tex&amp;gt;Q_d&amp;lt;/tex&amp;gt;.add(&amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt;)           &lt;br /&gt;
    &amp;lt;tex&amp;gt;T_d&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;\{q \in Q_d \mid \exists p \in T : p \in q\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''return''' &amp;lt;tex&amp;gt;\langle \Sigma, Q_d, \{s\}, T_d, \delta_d \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Асимптотика===&lt;br /&gt;
Так как количество подмножеств множества состояний НКА не более, чем &amp;lt;tex&amp;gt;2^n&amp;lt;/tex&amp;gt;, а каждое подмножество мы обрабатываем ровно один раз за время &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;, получаем верхнюю оценку времени работы алгоритма {{---}} &amp;lt;tex&amp;gt;O(n \cdot 2^n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
Пусть нам дан [[Недетерминированные конечные автоматы|недетерминированный конечный автомат]]: &lt;br /&gt;
&lt;br /&gt;
[[Файл:DKA.png|250px]]&lt;br /&gt;
&lt;br /&gt;
По нашему заданию эквивалентного ДКА мы получаем: &lt;br /&gt;
&lt;br /&gt;
[[Файл:NKA_definition.png|250px]]&lt;br /&gt;
&lt;br /&gt;
#Помещаем в очередь множество из одной стартовой вершины — &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\{1\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Достаём из очереди множество &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1\}, a) = \{1, 2\}&amp;lt;/tex&amp;gt;, кладём множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь: &amp;lt;tex&amp;gt;Q = \{\{1, 2\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1\}, b) = \{1\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#Достаём из очереди множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1, 2\}, a) = \{1, 2\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1, 2\}, b) = \{1, 2\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#Помечаем все терминальные вершины, в данном случае — &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем ДКА, эквивалентный исходному: &lt;br /&gt;
&lt;br /&gt;
[[Файл:NKA_algorithm.png|250px]].&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
&lt;br /&gt;
* [[Регулярные языки: два определения и их эквивалентность]]&lt;br /&gt;
* [[Минимизация ДКА, алгоритм за O(n^2) с построением пар различимых состояний]]&lt;br /&gt;
* [[Теорема Клини (совпадение классов автоматных и регулярных языков)]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* ''Серебряков В.А.'' Теория и реализация языков программирования. М.: МЗ-Пресс, 2003 (1-е изд.) и 2006 (2-е изд) — С. 294. — ISBN 5-94073-094-9&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Автоматы и регулярные языки]]&lt;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE_%D0%9D%D0%9A%D0%90_%D1%8D%D0%BA%D0%B2%D0%B8%D0%B2%D0%B0%D0%BB%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%94%D0%9A%D0%90,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A2%D0%BE%D0%BC%D0%BF%D1%81%D0%BE%D0%BD%D0%B0&amp;diff=43470</id>
		<title>Построение по НКА эквивалентного ДКА, алгоритм Томпсона</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE_%D0%9D%D0%9A%D0%90_%D1%8D%D0%BA%D0%B2%D0%B8%D0%B2%D0%B0%D0%BB%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%94%D0%9A%D0%90,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A2%D0%BE%D0%BC%D0%BF%D1%81%D0%BE%D0%BD%D0%B0&amp;diff=43470"/>
				<updated>2015-01-06T08:00:33Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: /* Алгоритм */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Описание ==&lt;br /&gt;
Алгоритм Томпсона строит по [[Недетерминированные конечные автоматы|НКА]] эквивалентный [[Детерминированные конечные автоматы|ДКА]] следующим образом:&lt;br /&gt;
* Начало.&lt;br /&gt;
* '''Шаг 1.''' Помещаем в очередь &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; множество, состоящее только из стартовой вершины.&lt;br /&gt;
* '''Шаг 2.''' Затем, пока очередь не пуста выполняем следующие действия:&lt;br /&gt;
** Достаем из очереди множество, назовем его &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt;&lt;br /&gt;
** Для всех &amp;lt;tex&amp;gt;c \in \Sigma&amp;lt;/tex&amp;gt; посмотрим в какое состояние ведет переход по символу &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; из каждого состояния в &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt;. Полученное множество состояний положим в очередь &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; только если оно не лежало там раньше. Каждое такое множество в итоговом ДКА будет отдельной вершиной, в которую будут вести переходы по соответствующим символам.&lt;br /&gt;
** Если в множестве &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; хотя бы одна из вершин была терминальной в НКА, то соответствующая данному множеству вершина в ДКА также будет терминальной.&lt;br /&gt;
* Конец.&lt;br /&gt;
&lt;br /&gt;
== Построение эквивалентного ДКА по НКА ==&lt;br /&gt;
&lt;br /&gt;
Пусть нам дан произвольный НКА: &amp;lt;tex&amp;gt;\langle \Sigma , Q, s \in Q, T \subset Q, \delta : Q \times \Sigma \to 2^Q \rangle&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Построим по нему следующий ДКА: &amp;lt;tex&amp;gt;\langle \Sigma , Q_d, s_d \in Q_d, T_d \subset Q_d, \delta_d : Q_d \times \Sigma \to Q_d \rangle&amp;lt;/tex&amp;gt;, где:&lt;br /&gt;
# &amp;lt;tex&amp;gt;Q_d = \{q_d \mid q_d \subset 2^Q \}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;s_d = \{s\}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;T_d = \{q \in Q_d \mid \exists p \in T : p \in q\}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;\delta_d(q, c) = \{ \delta(a, c) \mid a \in q \}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Доказательство эквивалентности===&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
Построенный ДКА эквивалентен данному НКА.&lt;br /&gt;
|proof=&lt;br /&gt;
#Докажем, что любое слово, которое принимает НКА, будет принято построенным ДКА. Заметим, что &amp;lt;tex&amp;gt;\forall q \in q_d, \forall c \in \Sigma, \forall p \in \delta(q, c): p \in \delta_d(q_d, c)&amp;lt;/tex&amp;gt;. Рассмотрим слово &amp;lt;tex&amp;gt;w=w_1 \dots w_m&amp;lt;/tex&amp;gt;, которое принимает автомат НКА: &amp;lt;tex&amp;gt;\langle s, w_1w_2 \dots w_m \rangle \vdash \langle u_1, w_2 \dots w_m \rangle \vdash \langle u_m, \varepsilon \rangle, u_m \in T&amp;lt;/tex&amp;gt;. Проверим, что построенный ДКА тоже принимает это слово. Заметим, что &amp;lt;tex&amp;gt;s \in s_d&amp;lt;/tex&amp;gt;, а, значит, исходя из нашего наблюдения, мы получаем, что &amp;lt;tex&amp;gt;u_1 \in {u_d}_1&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;{u_d}_1 = \delta_d(s, w_1)&amp;lt;/tex&amp;gt;. Далее, несложно заметить, что &amp;lt;tex&amp;gt;\forall i \leqslant m : u_i \in {u_d}_i&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\langle s_d, w_1w_2 \dots w_m \rangle \vdash \langle {u_d}_1, w_2 \dots w_m \rangle \vdash \langle {u_d}_i, w_{i + 1} \dots w_m\rangle&amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;tex&amp;gt;u_m \in {u_d}_m&amp;lt;/tex&amp;gt;, а из определения терминальных состояний в построенном ДКА мы получаем, что &amp;lt;tex&amp;gt;{u_d}_m \in T_d&amp;lt;/tex&amp;gt;, то есть наш ДКА тоже принимает cлово &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Докажем, что любое слово, которое принимает построенный ДКА, принимает и НКА. Сначала сделаем наблюдение, что если &amp;lt;tex&amp;gt;q_d=\{q\}&amp;lt;/tex&amp;gt;, и мы из него достигли по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; какого-то состояния &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\forall p \in p_d&amp;lt;/tex&amp;gt; существует путь из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; в НКА по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим слово &amp;lt;tex&amp;gt;w=w_1 \dots w_m&amp;lt;/tex&amp;gt;, которое принимает автомат ДКА: &amp;lt;tex&amp;gt;\langle s_d, w_1w_2 \dots w_m \rangle \vdash \langle {u_d}_1, w_2 \dots w_m \rangle \vdash \langle {u_d}_m, \varepsilon \rangle, {u_d}_m \in T_d&amp;lt;/tex&amp;gt;. Проверим, что НКА тоже принимает это слово. Так как &amp;lt;tex&amp;gt;s_d = \{s\}&amp;lt;/tex&amp;gt;, и мы из &amp;lt;tex&amp;gt;s_d&amp;lt;/tex&amp;gt; достигли &amp;lt;tex&amp;gt;{u_d}_m \in T_d&amp;lt;/tex&amp;gt;, возьмём любое терминальное состояние &amp;lt;tex&amp;gt;u_m \in {u_d}_m&amp;lt;/tex&amp;gt;. По нашему наблюдению в НКА есть путь из &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;u_m&amp;lt;/tex&amp;gt; по строке &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;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;
* &amp;lt;tex&amp;gt;\mathtt{P}&amp;lt;/tex&amp;gt; {{---}} очередь состояний, соответствующих множествам, состоящих из состояний НКА. &lt;br /&gt;
* &amp;lt;tex&amp;gt;\mathtt{Q}&amp;lt;/tex&amp;gt; {{---}} массив множеств, соответствующих состояниям ДКА.&lt;br /&gt;
* &amp;lt;tex&amp;gt;\mathtt{s}&amp;lt;/tex&amp;gt; {{---}} стартовое состояние НКА.&lt;br /&gt;
 '''Automaton''' getDFAbyNFA(&amp;lt;tex&amp;gt;\langle \Sigma, Q_0, s, T_0, \delta_0 \rangle&amp;lt;/tex&amp;gt; : '''Automaton'''):&lt;br /&gt;
    &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;.push({s})&lt;br /&gt;
    &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;\varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''while''' &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt; \neq &amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
       &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;.pop(&amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''for''' &amp;lt;tex&amp;gt;c \in \Sigma&amp;lt;/tex&amp;gt;&lt;br /&gt;
          &amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;\varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
          '''for''' &amp;lt;tex&amp;gt;p \in p_d&amp;lt;/tex&amp;gt;&lt;br /&gt;
             &amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;q_d \cup \{ \delta_0(p, c) \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
             &amp;lt;tex&amp;gt;\delta(p_d, q_d)&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;&lt;br /&gt;
          '''if''' &amp;lt;tex&amp;gt;q_d \notin Q&amp;lt;/tex&amp;gt;&lt;br /&gt;
             &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt;)&lt;br /&gt;
             &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.add(&amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt;)           &lt;br /&gt;
    &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;\{q \in Q \mid \exists p \in T : p \in q\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''return''' &amp;lt;tex&amp;gt;\langle \Sigma, Q, \{s\}, T, \delta \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Асимптотика===&lt;br /&gt;
Так как количество подмножеств множества состояний НКА не более, чем &amp;lt;tex&amp;gt;2^n&amp;lt;/tex&amp;gt;, а каждое подмножество мы обрабатываем ровно один раз за время &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;, получаем верхнюю оценку времени работы алгоритма {{---}} &amp;lt;tex&amp;gt;O(n \cdot 2^n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
Пусть нам дан [[Недетерминированные конечные автоматы|недетерминированный конечный автомат]]: &lt;br /&gt;
&lt;br /&gt;
[[Файл:DKA.png|250px]]&lt;br /&gt;
&lt;br /&gt;
По нашему заданию эквивалентного ДКА мы получаем: &lt;br /&gt;
&lt;br /&gt;
[[Файл:NKA_definition.png|250px]]&lt;br /&gt;
&lt;br /&gt;
#Помещаем в очередь множество из одной стартовой вершины — &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\{1\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Достаём из очереди множество &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1\}, a) = \{1, 2\}&amp;lt;/tex&amp;gt;, кладём множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь: &amp;lt;tex&amp;gt;Q = \{\{1, 2\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1\}, b) = \{1\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#Достаём из очереди множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1, 2\}, a) = \{1, 2\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1, 2\}, b) = \{1, 2\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#Помечаем все терминальные вершины, в данном случае — &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем ДКА, эквивалентный исходному: &lt;br /&gt;
&lt;br /&gt;
[[Файл:NKA_algorithm.png|250px]].&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
&lt;br /&gt;
* [[Регулярные языки: два определения и их эквивалентность]]&lt;br /&gt;
* [[Минимизация ДКА, алгоритм за O(n^2) с построением пар различимых состояний]]&lt;br /&gt;
* [[Теорема Клини (совпадение классов автоматных и регулярных языков)]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* ''Серебряков В.А.'' Теория и реализация языков программирования. М.: МЗ-Пресс, 2003 (1-е изд.) и 2006 (2-е изд) — С. 294. — ISBN 5-94073-094-9&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Автоматы и регулярные языки]]&lt;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE_%D0%9D%D0%9A%D0%90_%D1%8D%D0%BA%D0%B2%D0%B8%D0%B2%D0%B0%D0%BB%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%94%D0%9A%D0%90,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A2%D0%BE%D0%BC%D0%BF%D1%81%D0%BE%D0%BD%D0%B0&amp;diff=43469</id>
		<title>Построение по НКА эквивалентного ДКА, алгоритм Томпсона</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE_%D0%9D%D0%9A%D0%90_%D1%8D%D0%BA%D0%B2%D0%B8%D0%B2%D0%B0%D0%BB%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%94%D0%9A%D0%90,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A2%D0%BE%D0%BC%D0%BF%D1%81%D0%BE%D0%BD%D0%B0&amp;diff=43469"/>
				<updated>2015-01-06T07:54:57Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: /* Алгоритм */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Описание ==&lt;br /&gt;
Алгоритм Томпсона строит по [[Недетерминированные конечные автоматы|НКА]] эквивалентный [[Детерминированные конечные автоматы|ДКА]] следующим образом:&lt;br /&gt;
* Начало.&lt;br /&gt;
* '''Шаг 1.''' Помещаем в очередь &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; множество, состоящее только из стартовой вершины.&lt;br /&gt;
* '''Шаг 2.''' Затем, пока очередь не пуста выполняем следующие действия:&lt;br /&gt;
** Достаем из очереди множество, назовем его &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt;&lt;br /&gt;
** Для всех &amp;lt;tex&amp;gt;c \in \Sigma&amp;lt;/tex&amp;gt; посмотрим в какое состояние ведет переход по символу &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; из каждого состояния в &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt;. Полученное множество состояний положим в очередь &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; только если оно не лежало там раньше. Каждое такое множество в итоговом ДКА будет отдельной вершиной, в которую будут вести переходы по соответствующим символам.&lt;br /&gt;
** Если в множестве &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; хотя бы одна из вершин была терминальной в НКА, то соответствующая данному множеству вершина в ДКА также будет терминальной.&lt;br /&gt;
* Конец.&lt;br /&gt;
&lt;br /&gt;
== Построение эквивалентного ДКА по НКА ==&lt;br /&gt;
&lt;br /&gt;
Пусть нам дан произвольный НКА: &amp;lt;tex&amp;gt;\langle \Sigma , Q, s \in Q, T \subset Q, \delta : Q \times \Sigma \to 2^Q \rangle&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Построим по нему следующий ДКА: &amp;lt;tex&amp;gt;\langle \Sigma , Q_d, s_d \in Q_d, T_d \subset Q_d, \delta_d : Q_d \times \Sigma \to Q_d \rangle&amp;lt;/tex&amp;gt;, где:&lt;br /&gt;
# &amp;lt;tex&amp;gt;Q_d = \{q_d \mid q_d \subset 2^Q \}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;s_d = \{s\}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;T_d = \{q \in Q_d \mid \exists p \in T : p \in q\}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;\delta_d(q, c) = \{ \delta(a, c) \mid a \in q \}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Доказательство эквивалентности===&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
Построенный ДКА эквивалентен данному НКА.&lt;br /&gt;
|proof=&lt;br /&gt;
#Докажем, что любое слово, которое принимает НКА, будет принято построенным ДКА. Заметим, что &amp;lt;tex&amp;gt;\forall q \in q_d, \forall c \in \Sigma, \forall p \in \delta(q, c): p \in \delta_d(q_d, c)&amp;lt;/tex&amp;gt;. Рассмотрим слово &amp;lt;tex&amp;gt;w=w_1 \dots w_m&amp;lt;/tex&amp;gt;, которое принимает автомат НКА: &amp;lt;tex&amp;gt;\langle s, w_1w_2 \dots w_m \rangle \vdash \langle u_1, w_2 \dots w_m \rangle \vdash \langle u_m, \varepsilon \rangle, u_m \in T&amp;lt;/tex&amp;gt;. Проверим, что построенный ДКА тоже принимает это слово. Заметим, что &amp;lt;tex&amp;gt;s \in s_d&amp;lt;/tex&amp;gt;, а, значит, исходя из нашего наблюдения, мы получаем, что &amp;lt;tex&amp;gt;u_1 \in {u_d}_1&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;{u_d}_1 = \delta_d(s, w_1)&amp;lt;/tex&amp;gt;. Далее, несложно заметить, что &amp;lt;tex&amp;gt;\forall i \leqslant m : u_i \in {u_d}_i&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\langle s_d, w_1w_2 \dots w_m \rangle \vdash \langle {u_d}_1, w_2 \dots w_m \rangle \vdash \langle {u_d}_i, w_{i + 1} \dots w_m\rangle&amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;tex&amp;gt;u_m \in {u_d}_m&amp;lt;/tex&amp;gt;, а из определения терминальных состояний в построенном ДКА мы получаем, что &amp;lt;tex&amp;gt;{u_d}_m \in T_d&amp;lt;/tex&amp;gt;, то есть наш ДКА тоже принимает cлово &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Докажем, что любое слово, которое принимает построенный ДКА, принимает и НКА. Сначала сделаем наблюдение, что если &amp;lt;tex&amp;gt;q_d=\{q\}&amp;lt;/tex&amp;gt;, и мы из него достигли по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; какого-то состояния &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\forall p \in p_d&amp;lt;/tex&amp;gt; существует путь из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; в НКА по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим слово &amp;lt;tex&amp;gt;w=w_1 \dots w_m&amp;lt;/tex&amp;gt;, которое принимает автомат ДКА: &amp;lt;tex&amp;gt;\langle s_d, w_1w_2 \dots w_m \rangle \vdash \langle {u_d}_1, w_2 \dots w_m \rangle \vdash \langle {u_d}_m, \varepsilon \rangle, {u_d}_m \in T_d&amp;lt;/tex&amp;gt;. Проверим, что НКА тоже принимает это слово. Так как &amp;lt;tex&amp;gt;s_d = \{s\}&amp;lt;/tex&amp;gt;, и мы из &amp;lt;tex&amp;gt;s_d&amp;lt;/tex&amp;gt; достигли &amp;lt;tex&amp;gt;{u_d}_m \in T_d&amp;lt;/tex&amp;gt;, возьмём любое терминальное состояние &amp;lt;tex&amp;gt;u_m \in {u_d}_m&amp;lt;/tex&amp;gt;. По нашему наблюдению в НКА есть путь из &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;u_m&amp;lt;/tex&amp;gt; по строке &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;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;
&amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; {{---}} очередь состояний, соответствующих множествам, состоящих из состояний НКА. &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; {{---}} массив множеств, соответствующих состояниям ДКА.&lt;br /&gt;
&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; {{---}} стартовое состояние НКА.&lt;br /&gt;
 '''Automaton''' getDFAbyNFA(&amp;lt;tex&amp;gt;\langle \Sigma, Q_0, s, T_0, \delta_0 \rangle&amp;lt;/tex&amp;gt; : '''Automaton'''):&lt;br /&gt;
    &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;.push({s})&lt;br /&gt;
    &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;\varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''while''' &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt; \neq &amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
       &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;.pop(&amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''for''' &amp;lt;tex&amp;gt;c \in \Sigma&amp;lt;/tex&amp;gt;&lt;br /&gt;
          &amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;\varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
          '''for''' &amp;lt;tex&amp;gt;p \in p_d&amp;lt;/tex&amp;gt;&lt;br /&gt;
             &amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;q_d \cup \{ \delta_0(p, c) \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
             &amp;lt;tex&amp;gt;\delta(p_d, q_d)&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;&lt;br /&gt;
          '''if''' &amp;lt;tex&amp;gt;q_d \notin Q&amp;lt;/tex&amp;gt;&lt;br /&gt;
             &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt;)&lt;br /&gt;
             &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.add(&amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt;)           &lt;br /&gt;
    &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;\{q \in Q \mid \exists p \in T : p \in q\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''return''' &amp;lt;tex&amp;gt;\langle \Sigma, Q, \{s\}, T, \delta \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Асимптотика===&lt;br /&gt;
Так как количество подмножеств множества состояний НКА не более, чем &amp;lt;tex&amp;gt;2^n&amp;lt;/tex&amp;gt;, а каждое подмножество мы обрабатываем ровно один раз за время &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;, получаем верхнюю оценку времени работы алгоритма {{---}} &amp;lt;tex&amp;gt;O(n \cdot 2^n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
Пусть нам дан [[Недетерминированные конечные автоматы|недетерминированный конечный автомат]]: &lt;br /&gt;
&lt;br /&gt;
[[Файл:DKA.png|250px]]&lt;br /&gt;
&lt;br /&gt;
По нашему заданию эквивалентного ДКА мы получаем: &lt;br /&gt;
&lt;br /&gt;
[[Файл:NKA_definition.png|250px]]&lt;br /&gt;
&lt;br /&gt;
#Помещаем в очередь множество из одной стартовой вершины — &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\{1\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Достаём из очереди множество &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1\}, a) = \{1, 2\}&amp;lt;/tex&amp;gt;, кладём множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь: &amp;lt;tex&amp;gt;Q = \{\{1, 2\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1\}, b) = \{1\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#Достаём из очереди множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1, 2\}, a) = \{1, 2\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1, 2\}, b) = \{1, 2\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#Помечаем все терминальные вершины, в данном случае — &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем ДКА, эквивалентный исходному: &lt;br /&gt;
&lt;br /&gt;
[[Файл:NKA_algorithm.png|250px]].&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
&lt;br /&gt;
* [[Регулярные языки: два определения и их эквивалентность]]&lt;br /&gt;
* [[Минимизация ДКА, алгоритм за O(n^2) с построением пар различимых состояний]]&lt;br /&gt;
* [[Теорема Клини (совпадение классов автоматных и регулярных языков)]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* ''Серебряков В.А.'' Теория и реализация языков программирования. М.: МЗ-Пресс, 2003 (1-е изд.) и 2006 (2-е изд) — С. 294. — ISBN 5-94073-094-9&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Автоматы и регулярные языки]]&lt;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE_%D0%9D%D0%9A%D0%90_%D1%8D%D0%BA%D0%B2%D0%B8%D0%B2%D0%B0%D0%BB%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%94%D0%9A%D0%90,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A2%D0%BE%D0%BC%D0%BF%D1%81%D0%BE%D0%BD%D0%B0&amp;diff=43468</id>
		<title>Построение по НКА эквивалентного ДКА, алгоритм Томпсона</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE_%D0%9D%D0%9A%D0%90_%D1%8D%D0%BA%D0%B2%D0%B8%D0%B2%D0%B0%D0%BB%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%94%D0%9A%D0%90,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A2%D0%BE%D0%BC%D0%BF%D1%81%D0%BE%D0%BD%D0%B0&amp;diff=43468"/>
				<updated>2015-01-06T07:52:48Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: /* Алгоритм */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Описание ==&lt;br /&gt;
Алгоритм Томпсона строит по [[Недетерминированные конечные автоматы|НКА]] эквивалентный [[Детерминированные конечные автоматы|ДКА]] следующим образом:&lt;br /&gt;
* Начало.&lt;br /&gt;
* '''Шаг 1.''' Помещаем в очередь &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; множество, состоящее только из стартовой вершины.&lt;br /&gt;
* '''Шаг 2.''' Затем, пока очередь не пуста выполняем следующие действия:&lt;br /&gt;
** Достаем из очереди множество, назовем его &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt;&lt;br /&gt;
** Для всех &amp;lt;tex&amp;gt;c \in \Sigma&amp;lt;/tex&amp;gt; посмотрим в какое состояние ведет переход по символу &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; из каждого состояния в &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt;. Полученное множество состояний положим в очередь &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; только если оно не лежало там раньше. Каждое такое множество в итоговом ДКА будет отдельной вершиной, в которую будут вести переходы по соответствующим символам.&lt;br /&gt;
** Если в множестве &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; хотя бы одна из вершин была терминальной в НКА, то соответствующая данному множеству вершина в ДКА также будет терминальной.&lt;br /&gt;
* Конец.&lt;br /&gt;
&lt;br /&gt;
== Построение эквивалентного ДКА по НКА ==&lt;br /&gt;
&lt;br /&gt;
Пусть нам дан произвольный НКА: &amp;lt;tex&amp;gt;\langle \Sigma , Q, s \in Q, T \subset Q, \delta : Q \times \Sigma \to 2^Q \rangle&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Построим по нему следующий ДКА: &amp;lt;tex&amp;gt;\langle \Sigma , Q_d, s_d \in Q_d, T_d \subset Q_d, \delta_d : Q_d \times \Sigma \to Q_d \rangle&amp;lt;/tex&amp;gt;, где:&lt;br /&gt;
# &amp;lt;tex&amp;gt;Q_d = \{q_d \mid q_d \subset 2^Q \}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;s_d = \{s\}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;T_d = \{q \in Q_d \mid \exists p \in T : p \in q\}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;\delta_d(q, c) = \{ \delta(a, c) \mid a \in q \}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Доказательство эквивалентности===&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
Построенный ДКА эквивалентен данному НКА.&lt;br /&gt;
|proof=&lt;br /&gt;
#Докажем, что любое слово, которое принимает НКА, будет принято построенным ДКА. Заметим, что &amp;lt;tex&amp;gt;\forall q \in q_d, \forall c \in \Sigma, \forall p \in \delta(q, c): p \in \delta_d(q_d, c)&amp;lt;/tex&amp;gt;. Рассмотрим слово &amp;lt;tex&amp;gt;w=w_1 \dots w_m&amp;lt;/tex&amp;gt;, которое принимает автомат НКА: &amp;lt;tex&amp;gt;\langle s, w_1w_2 \dots w_m \rangle \vdash \langle u_1, w_2 \dots w_m \rangle \vdash \langle u_m, \varepsilon \rangle, u_m \in T&amp;lt;/tex&amp;gt;. Проверим, что построенный ДКА тоже принимает это слово. Заметим, что &amp;lt;tex&amp;gt;s \in s_d&amp;lt;/tex&amp;gt;, а, значит, исходя из нашего наблюдения, мы получаем, что &amp;lt;tex&amp;gt;u_1 \in {u_d}_1&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;{u_d}_1 = \delta_d(s, w_1)&amp;lt;/tex&amp;gt;. Далее, несложно заметить, что &amp;lt;tex&amp;gt;\forall i \leqslant m : u_i \in {u_d}_i&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\langle s_d, w_1w_2 \dots w_m \rangle \vdash \langle {u_d}_1, w_2 \dots w_m \rangle \vdash \langle {u_d}_i, w_{i + 1} \dots w_m\rangle&amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;tex&amp;gt;u_m \in {u_d}_m&amp;lt;/tex&amp;gt;, а из определения терминальных состояний в построенном ДКА мы получаем, что &amp;lt;tex&amp;gt;{u_d}_m \in T_d&amp;lt;/tex&amp;gt;, то есть наш ДКА тоже принимает cлово &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Докажем, что любое слово, которое принимает построенный ДКА, принимает и НКА. Сначала сделаем наблюдение, что если &amp;lt;tex&amp;gt;q_d=\{q\}&amp;lt;/tex&amp;gt;, и мы из него достигли по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; какого-то состояния &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\forall p \in p_d&amp;lt;/tex&amp;gt; существует путь из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; в НКА по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим слово &amp;lt;tex&amp;gt;w=w_1 \dots w_m&amp;lt;/tex&amp;gt;, которое принимает автомат ДКА: &amp;lt;tex&amp;gt;\langle s_d, w_1w_2 \dots w_m \rangle \vdash \langle {u_d}_1, w_2 \dots w_m \rangle \vdash \langle {u_d}_m, \varepsilon \rangle, {u_d}_m \in T_d&amp;lt;/tex&amp;gt;. Проверим, что НКА тоже принимает это слово. Так как &amp;lt;tex&amp;gt;s_d = \{s\}&amp;lt;/tex&amp;gt;, и мы из &amp;lt;tex&amp;gt;s_d&amp;lt;/tex&amp;gt; достигли &amp;lt;tex&amp;gt;{u_d}_m \in T_d&amp;lt;/tex&amp;gt;, возьмём любое терминальное состояние &amp;lt;tex&amp;gt;u_m \in {u_d}_m&amp;lt;/tex&amp;gt;. По нашему наблюдению в НКА есть путь из &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;u_m&amp;lt;/tex&amp;gt; по строке &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;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;
&amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; {{---}} очередь состояний, соответствующих множествам, состоящих из состояний НКА. &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; {{---}} массив множеств, соответствующих состояниям ДКА.&lt;br /&gt;
&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; {{---}} стартовое состояние НКА.&lt;br /&gt;
 '''Automaton''' getDFAbyNFA(&amp;lt;tex&amp;gt;\langle \Sigma, Q_0, s, T_0, \delta_0 \rangle&amp;lt;/tex&amp;gt; : '''Automaton'''):&lt;br /&gt;
    &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;.push({s})&lt;br /&gt;
    &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;\varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''while''' (&amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt; \neq &amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\varnothing &amp;lt;/tex&amp;gt;)&lt;br /&gt;
       &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;.pop(&amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''for''' (&amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;\Sigma&amp;lt;/tex&amp;gt;)&lt;br /&gt;
          &amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;\varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
          '''for''' (&amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;) &lt;br /&gt;
             &amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;q_d \cup \{ \delta_0(p, c) \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
             &amp;lt;tex&amp;gt;\delta(p_d, q_d)&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;&lt;br /&gt;
          '''if''' (&amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt; '''not in''' &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;)&lt;br /&gt;
             &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt;)&lt;br /&gt;
             &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.add(&amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt;)           &lt;br /&gt;
    &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;\{q \in Q \mid \exists p \in T : p \in q\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''return''' &amp;lt;tex&amp;gt;\langle \Sigma, Q, \{s\}, T, \delta \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Асимптотика===&lt;br /&gt;
Так как количество подмножеств множества состояний НКА не более, чем &amp;lt;tex&amp;gt;2^n&amp;lt;/tex&amp;gt;, а каждое подмножество мы обрабатываем ровно один раз за время &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;, получаем верхнюю оценку времени работы алгоритма {{---}} &amp;lt;tex&amp;gt;O(n \cdot 2^n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
Пусть нам дан [[Недетерминированные конечные автоматы|недетерминированный конечный автомат]]: &lt;br /&gt;
&lt;br /&gt;
[[Файл:DKA.png|250px]]&lt;br /&gt;
&lt;br /&gt;
По нашему заданию эквивалентного ДКА мы получаем: &lt;br /&gt;
&lt;br /&gt;
[[Файл:NKA_definition.png|250px]]&lt;br /&gt;
&lt;br /&gt;
#Помещаем в очередь множество из одной стартовой вершины — &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\{1\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Достаём из очереди множество &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1\}, a) = \{1, 2\}&amp;lt;/tex&amp;gt;, кладём множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь: &amp;lt;tex&amp;gt;Q = \{\{1, 2\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1\}, b) = \{1\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#Достаём из очереди множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1, 2\}, a) = \{1, 2\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1, 2\}, b) = \{1, 2\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#Помечаем все терминальные вершины, в данном случае — &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем ДКА, эквивалентный исходному: &lt;br /&gt;
&lt;br /&gt;
[[Файл:NKA_algorithm.png|250px]].&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
&lt;br /&gt;
* [[Регулярные языки: два определения и их эквивалентность]]&lt;br /&gt;
* [[Минимизация ДКА, алгоритм за O(n^2) с построением пар различимых состояний]]&lt;br /&gt;
* [[Теорема Клини (совпадение классов автоматных и регулярных языков)]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* ''Серебряков В.А.'' Теория и реализация языков программирования. М.: МЗ-Пресс, 2003 (1-е изд.) и 2006 (2-е изд) — С. 294. — ISBN 5-94073-094-9&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Автоматы и регулярные языки]]&lt;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE_%D0%9D%D0%9A%D0%90_%D1%8D%D0%BA%D0%B2%D0%B8%D0%B2%D0%B0%D0%BB%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%94%D0%9A%D0%90,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A2%D0%BE%D0%BC%D0%BF%D1%81%D0%BE%D0%BD%D0%B0&amp;diff=43458</id>
		<title>Построение по НКА эквивалентного ДКА, алгоритм Томпсона</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE_%D0%9D%D0%9A%D0%90_%D1%8D%D0%BA%D0%B2%D0%B8%D0%B2%D0%B0%D0%BB%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%94%D0%9A%D0%90,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A2%D0%BE%D0%BC%D0%BF%D1%81%D0%BE%D0%BD%D0%B0&amp;diff=43458"/>
				<updated>2015-01-05T17:01:55Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: /* Описание */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Описание ==&lt;br /&gt;
Алгоритм Томпсона строит по [[Недетерминированные конечные автоматы|НКА]] эквивалентный [[Детерминированные конечные автоматы|ДКА]] следующим образом:&lt;br /&gt;
* Начало.&lt;br /&gt;
* '''Шаг 1.''' Помещаем в очередь &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; множество, состоящее только из стартовой вершины.&lt;br /&gt;
* '''Шаг 2.''' Затем, пока очередь не пуста выполняем следующие действия:&lt;br /&gt;
** Достаем из очереди множество, назовем его &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt;&lt;br /&gt;
** Для каждого &amp;lt;tex&amp;gt;c \in \Sigma&amp;lt;/tex&amp;gt; посмотрим в какое состояние ведет переход по этому &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; для каждого состояния из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt;. Полученное множество состояний положим в очередь &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; только если оно не лежало там раньше. Каждое такое множество в итоговом ДКА будет отдельной вершиной, в которую будут вести переходы по соответствующим символам.&lt;br /&gt;
** Если в множестве &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; хотя бы одна из вершин была терминальной в НКА, то соответствующая данному множеству вершина в ДКА также будет терминальной.&lt;br /&gt;
* Конец.&lt;br /&gt;
&lt;br /&gt;
== Построение эквивалентного ДКА по НКА ==&lt;br /&gt;
&lt;br /&gt;
Пусть нам дан произвольный НКА: &amp;lt;tex&amp;gt;\langle \Sigma , Q, s \in Q, T \subset Q, \delta : Q \times \Sigma \to 2^Q \rangle&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Построим по нему следующий ДКА: &amp;lt;tex&amp;gt;\langle \Sigma , Q_d, s_d \in Q_d, T_d \subset Q_d, \delta_d : Q_d \times \Sigma \to Q_d \rangle&amp;lt;/tex&amp;gt;, где:&lt;br /&gt;
# &amp;lt;tex&amp;gt;Q_d = \{q_d \mid q_d \subset 2^Q \}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;s_d = \{s\}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;T_d = \{q \in Q_d \mid \exists p \in T : p \in q\}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;\delta_d(q, c) = \{ \delta(a, c) \mid a \in q \}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Доказательство эквивалентности===&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
Построенный ДКА эквивалентен данному НКА.&lt;br /&gt;
|proof=&lt;br /&gt;
#Докажем, что любое слово, которое принимает НКА, будет принято построенным ДКА. Заметим, что &amp;lt;tex&amp;gt;\forall q \in q_d, \forall c \in \Sigma, \forall p \in \delta(q, c): p \in \delta_d(q_d, c)&amp;lt;/tex&amp;gt;. Рассмотрим слово &amp;lt;tex&amp;gt;w=w_1 \dots w_m&amp;lt;/tex&amp;gt;, которое принимает автомат НКА: &amp;lt;tex&amp;gt;\langle s, w_1w_2 \dots w_m \rangle \vdash \langle u_1, w_2 \dots w_m \rangle \vdash \langle u_m, \varepsilon \rangle, u_m \in T&amp;lt;/tex&amp;gt;. Проверим, что построенный ДКА тоже принимает это слово. Заметим, что &amp;lt;tex&amp;gt;s \in s_d&amp;lt;/tex&amp;gt;, а, значит, исходя из нашего наблюдения, мы получаем, что &amp;lt;tex&amp;gt;u_1 \in {u_d}_1&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;{u_d}_1 = \delta_d(s, w_1)&amp;lt;/tex&amp;gt;. Далее, несложно заметить, что &amp;lt;tex&amp;gt;\forall i \leqslant m : u_i \in {u_d}_i&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\langle s_d, w_1w_2 \dots w_m \rangle \vdash \langle {u_d}_1, w_2 \dots w_m \rangle \vdash \langle {u_d}_i, w_{i + 1} \dots w_m\rangle&amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;tex&amp;gt;u_m \in {u_d}_m&amp;lt;/tex&amp;gt;, а из определения терминальных состояний в построенном ДКА мы получаем, что &amp;lt;tex&amp;gt;{u_d}_m \in T_d&amp;lt;/tex&amp;gt;, то есть наш ДКА тоже принимает cлово &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Докажем, что любое слово, которое принимает построенный ДКА, принимает и НКА. Сначала сделаем наблюдение, что если &amp;lt;tex&amp;gt;q_d=\{q\}&amp;lt;/tex&amp;gt;, и мы из него достигли по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; какого-то состояния &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\forall p \in p_d&amp;lt;/tex&amp;gt; существует путь из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; в НКА по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим слово &amp;lt;tex&amp;gt;w=w_1 \dots w_m&amp;lt;/tex&amp;gt;, которое принимает автомат ДКА: &amp;lt;tex&amp;gt;\langle s_d, w_1w_2 \dots w_m \rangle \vdash \langle {u_d}_1, w_2 \dots w_m \rangle \vdash \langle {u_d}_m, \varepsilon \rangle, {u_d}_m \in T_d&amp;lt;/tex&amp;gt;. Проверим, что НКА тоже принимает это слово. Так как &amp;lt;tex&amp;gt;s_d = \{s\}&amp;lt;/tex&amp;gt;, и мы из &amp;lt;tex&amp;gt;s_d&amp;lt;/tex&amp;gt; достигли &amp;lt;tex&amp;gt;{u_d}_m \in T_d&amp;lt;/tex&amp;gt;, возьмём любое терминальное состояние &amp;lt;tex&amp;gt;u_m \in {u_d}_m&amp;lt;/tex&amp;gt;. По нашему наблюдению в НКА есть путь из &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;u_m&amp;lt;/tex&amp;gt; по строке &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;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;
&amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; {{---}} очередь состояний, соответствующих множествам, состоящих из состояний НКА. &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; {{---}} массив множеств, соответствующих состояниям ДКА.&lt;br /&gt;
&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; {{---}} стартовое состояние НКА.&lt;br /&gt;
 '''Automaton''' getDFAbyNFA(&amp;lt;tex&amp;gt;\langle \Sigma, Q_0, s, T_0, \delta_0 \rangle&amp;lt;/tex&amp;gt; : '''Automaton'''):&lt;br /&gt;
    &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;.push({s})&lt;br /&gt;
    &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;\varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''while''' (&amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt; \neq &amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\varnothing &amp;lt;/tex&amp;gt;)&lt;br /&gt;
       &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;.pop(&amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''for''' (&amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;\Sigma&amp;lt;/tex&amp;gt;)&lt;br /&gt;
          &amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;\varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
          '''for''' (&amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;) &lt;br /&gt;
             &amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;q_d \cup \{ \delta_0(p, c) \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
          '''if''' (&amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt; '''not in''' &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;)&lt;br /&gt;
             &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt;)&lt;br /&gt;
             &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.add(&amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt;)   &lt;br /&gt;
             &amp;lt;tex&amp;gt;\delta(p_d, q_d)&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''for''' (&amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''if''' (&amp;lt;tex&amp;gt;\exists q_d&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;q: q_d&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;T_0&amp;lt;/tex&amp;gt;)&lt;br /&gt;
         &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;.add&amp;lt;tex&amp;gt;(q)&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''return''' &amp;lt;tex&amp;gt;\langle \Sigma, Q, \{s\}, T, \delta \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Асимптотика===&lt;br /&gt;
Так как количество подмножеств множества состояний НКА не более, чем &amp;lt;tex&amp;gt;2^n&amp;lt;/tex&amp;gt;, а каждое подмножество мы обрабатываем ровно один раз за время &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;, получаем верхнюю оценку времени работы алгоритма {{---}} &amp;lt;tex&amp;gt;O(n \cdot 2^n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
Пусть нам дан [[Недетерминированные конечные автоматы|недетерминированный конечный автомат]]: &lt;br /&gt;
&lt;br /&gt;
[[Файл:DKA.png|250px]]&lt;br /&gt;
&lt;br /&gt;
По нашему заданию эквивалентного ДКА мы получаем: &lt;br /&gt;
&lt;br /&gt;
[[Файл:NKA_definition.png|250px]]&lt;br /&gt;
&lt;br /&gt;
#Помещаем в очередь множество из одной стартовой вершины — &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\{1\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Достаём из очереди множество &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1\}, a) = \{1, 2\}&amp;lt;/tex&amp;gt;, кладём множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь: &amp;lt;tex&amp;gt;Q = \{\{1, 2\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1\}, b) = \{1\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#Достаём из очереди множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1, 2\}, a) = \{1, 2\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1, 2\}, b) = \{1, 2\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#Помечаем все терминальные вершины, в данном случае — &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем ДКА, эквивалентный исходному: &lt;br /&gt;
&lt;br /&gt;
[[Файл:NKA_algorithm.png|250px]].&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
&lt;br /&gt;
* [[Регулярные языки: два определения и их эквивалентность]]&lt;br /&gt;
* [[Минимизация ДКА, алгоритм за O(n^2) с построением пар различимых состояний]]&lt;br /&gt;
* [[Теорема Клини (совпадение классов автоматных и регулярных языков)]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* ''Серебряков В.А.'' Теория и реализация языков программирования. М.: МЗ-Пресс, 2003 (1-е изд.) и 2006 (2-е изд) — С. 294. — ISBN 5-94073-094-9&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Автоматы и регулярные языки]]&lt;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE_%D0%9D%D0%9A%D0%90_%D1%8D%D0%BA%D0%B2%D0%B8%D0%B2%D0%B0%D0%BB%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%94%D0%9A%D0%90,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A2%D0%BE%D0%BC%D0%BF%D1%81%D0%BE%D0%BD%D0%B0&amp;diff=43457</id>
		<title>Построение по НКА эквивалентного ДКА, алгоритм Томпсона</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE_%D0%9D%D0%9A%D0%90_%D1%8D%D0%BA%D0%B2%D0%B8%D0%B2%D0%B0%D0%BB%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%94%D0%9A%D0%90,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A2%D0%BE%D0%BC%D0%BF%D1%81%D0%BE%D0%BD%D0%B0&amp;diff=43457"/>
				<updated>2015-01-05T16:47:12Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: /* Алгоритм */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Описание ==&lt;br /&gt;
Алгоритм Томпсона строит по [[Недетерминированные конечные автоматы|НКА]] эквивалентный [[Детерминированные конечные автоматы|ДКА]] следующим образом:&lt;br /&gt;
* Начало.&lt;br /&gt;
* '''Шаг 1.''' Помещаем в очередь &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; множество, состоящее только из стартовой вершины.&lt;br /&gt;
* '''Шаг 2.''' Затем, пока очередь не пуста выполняем следующие действия:&lt;br /&gt;
** Достаем из очереди множество, назовем его &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt;&lt;br /&gt;
** Для каждого &amp;lt;tex&amp;gt;c \in \Sigma&amp;lt;/tex&amp;gt; построим множество, содержащее состояния, в которые ведет символ &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; из каждого состояния из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt;. Затем положим построенное множество в очередь &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; только если оно не лежало там раньше. Каждое такое множество в итоговом ДКА будет отдельной вершиной, в которую будут вести переходы по соответствующим символам.&lt;br /&gt;
** Если в множестве &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; хотя бы одна из вершин была терминальной в НКА, то соответствующая данному множеству вершина в ДКА также будет терминальной.&lt;br /&gt;
* Конец.&lt;br /&gt;
&lt;br /&gt;
== Построение эквивалентного ДКА по НКА ==&lt;br /&gt;
&lt;br /&gt;
Пусть нам дан произвольный НКА: &amp;lt;tex&amp;gt;\langle \Sigma , Q, s \in Q, T \subset Q, \delta : Q \times \Sigma \to 2^Q \rangle&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Построим по нему следующий ДКА: &amp;lt;tex&amp;gt;\langle \Sigma , Q_d, s_d \in Q_d, T_d \subset Q_d, \delta_d : Q_d \times \Sigma \to Q_d \rangle&amp;lt;/tex&amp;gt;, где:&lt;br /&gt;
# &amp;lt;tex&amp;gt;Q_d = \{q_d \mid q_d \subset 2^Q \}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;s_d = \{s\}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;T_d = \{q \in Q_d \mid \exists p \in T : p \in q\}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;\delta_d(q, c) = \{ \delta(a, c) \mid a \in q \}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Доказательство эквивалентности===&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
Построенный ДКА эквивалентен данному НКА.&lt;br /&gt;
|proof=&lt;br /&gt;
#Докажем, что любое слово, которое принимает НКА, будет принято построенным ДКА. Заметим, что &amp;lt;tex&amp;gt;\forall q \in q_d, \forall c \in \Sigma, \forall p \in \delta(q, c): p \in \delta_d(q_d, c)&amp;lt;/tex&amp;gt;. Рассмотрим слово &amp;lt;tex&amp;gt;w=w_1 \dots w_m&amp;lt;/tex&amp;gt;, которое принимает автомат НКА: &amp;lt;tex&amp;gt;\langle s, w_1w_2 \dots w_m \rangle \vdash \langle u_1, w_2 \dots w_m \rangle \vdash \langle u_m, \varepsilon \rangle, u_m \in T&amp;lt;/tex&amp;gt;. Проверим, что построенный ДКА тоже принимает это слово. Заметим, что &amp;lt;tex&amp;gt;s \in s_d&amp;lt;/tex&amp;gt;, а, значит, исходя из нашего наблюдения, мы получаем, что &amp;lt;tex&amp;gt;u_1 \in {u_d}_1&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;{u_d}_1 = \delta_d(s, w_1)&amp;lt;/tex&amp;gt;. Далее, несложно заметить, что &amp;lt;tex&amp;gt;\forall i \leqslant m : u_i \in {u_d}_i&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\langle s_d, w_1w_2 \dots w_m \rangle \vdash \langle {u_d}_1, w_2 \dots w_m \rangle \vdash \langle {u_d}_i, w_{i + 1} \dots w_m\rangle&amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;tex&amp;gt;u_m \in {u_d}_m&amp;lt;/tex&amp;gt;, а из определения терминальных состояний в построенном ДКА мы получаем, что &amp;lt;tex&amp;gt;{u_d}_m \in T_d&amp;lt;/tex&amp;gt;, то есть наш ДКА тоже принимает cлово &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Докажем, что любое слово, которое принимает построенный ДКА, принимает и НКА. Сначала сделаем наблюдение, что если &amp;lt;tex&amp;gt;q_d=\{q\}&amp;lt;/tex&amp;gt;, и мы из него достигли по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; какого-то состояния &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\forall p \in p_d&amp;lt;/tex&amp;gt; существует путь из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; в НКА по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим слово &amp;lt;tex&amp;gt;w=w_1 \dots w_m&amp;lt;/tex&amp;gt;, которое принимает автомат ДКА: &amp;lt;tex&amp;gt;\langle s_d, w_1w_2 \dots w_m \rangle \vdash \langle {u_d}_1, w_2 \dots w_m \rangle \vdash \langle {u_d}_m, \varepsilon \rangle, {u_d}_m \in T_d&amp;lt;/tex&amp;gt;. Проверим, что НКА тоже принимает это слово. Так как &amp;lt;tex&amp;gt;s_d = \{s\}&amp;lt;/tex&amp;gt;, и мы из &amp;lt;tex&amp;gt;s_d&amp;lt;/tex&amp;gt; достигли &amp;lt;tex&amp;gt;{u_d}_m \in T_d&amp;lt;/tex&amp;gt;, возьмём любое терминальное состояние &amp;lt;tex&amp;gt;u_m \in {u_d}_m&amp;lt;/tex&amp;gt;. По нашему наблюдению в НКА есть путь из &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;u_m&amp;lt;/tex&amp;gt; по строке &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;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;
&amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; {{---}} очередь состояний, соответствующих множествам, состоящих из состояний НКА. &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; {{---}} массив множеств, соответствующих состояниям ДКА.&lt;br /&gt;
&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; {{---}} стартовое состояние НКА.&lt;br /&gt;
 '''Automaton''' getDFAbyNFA(&amp;lt;tex&amp;gt;\langle \Sigma, Q_0, s, T_0, \delta_0 \rangle&amp;lt;/tex&amp;gt; : '''Automaton'''):&lt;br /&gt;
    &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;.push({s})&lt;br /&gt;
    &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;\varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''while''' (&amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt; \neq &amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\varnothing &amp;lt;/tex&amp;gt;)&lt;br /&gt;
       &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;.pop(&amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''for''' (&amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;\Sigma&amp;lt;/tex&amp;gt;)&lt;br /&gt;
          &amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;\varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
          '''for''' (&amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;) &lt;br /&gt;
             &amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;q_d \cup \{ \delta_0(p, c) \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
          '''if''' (&amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt; '''not in''' &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;)&lt;br /&gt;
             &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt;)&lt;br /&gt;
             &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.add(&amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt;)   &lt;br /&gt;
             &amp;lt;tex&amp;gt;\delta(p_d, q_d)&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''for''' (&amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''if''' (&amp;lt;tex&amp;gt;\exists q_d&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;q: q_d&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;T_0&amp;lt;/tex&amp;gt;)&lt;br /&gt;
         &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;.add&amp;lt;tex&amp;gt;(q)&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''return''' &amp;lt;tex&amp;gt;\langle \Sigma, Q, \{s\}, T, \delta \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Асимптотика===&lt;br /&gt;
Так как количество подмножеств множества состояний НКА не более, чем &amp;lt;tex&amp;gt;2^n&amp;lt;/tex&amp;gt;, а каждое подмножество мы обрабатываем ровно один раз за время &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;, получаем верхнюю оценку времени работы алгоритма {{---}} &amp;lt;tex&amp;gt;O(n \cdot 2^n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
Пусть нам дан [[Недетерминированные конечные автоматы|недетерминированный конечный автомат]]: &lt;br /&gt;
&lt;br /&gt;
[[Файл:DKA.png|250px]]&lt;br /&gt;
&lt;br /&gt;
По нашему заданию эквивалентного ДКА мы получаем: &lt;br /&gt;
&lt;br /&gt;
[[Файл:NKA_definition.png|250px]]&lt;br /&gt;
&lt;br /&gt;
#Помещаем в очередь множество из одной стартовой вершины — &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\{1\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Достаём из очереди множество &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1\}, a) = \{1, 2\}&amp;lt;/tex&amp;gt;, кладём множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь: &amp;lt;tex&amp;gt;Q = \{\{1, 2\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1\}, b) = \{1\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#Достаём из очереди множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1, 2\}, a) = \{1, 2\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1, 2\}, b) = \{1, 2\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#Помечаем все терминальные вершины, в данном случае — &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем ДКА, эквивалентный исходному: &lt;br /&gt;
&lt;br /&gt;
[[Файл:NKA_algorithm.png|250px]].&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
&lt;br /&gt;
* [[Регулярные языки: два определения и их эквивалентность]]&lt;br /&gt;
* [[Минимизация ДКА, алгоритм за O(n^2) с построением пар различимых состояний]]&lt;br /&gt;
* [[Теорема Клини (совпадение классов автоматных и регулярных языков)]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* ''Серебряков В.А.'' Теория и реализация языков программирования. М.: МЗ-Пресс, 2003 (1-е изд.) и 2006 (2-е изд) — С. 294. — ISBN 5-94073-094-9&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Автоматы и регулярные языки]]&lt;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE_%D0%9D%D0%9A%D0%90_%D1%8D%D0%BA%D0%B2%D0%B8%D0%B2%D0%B0%D0%BB%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%94%D0%9A%D0%90,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A2%D0%BE%D0%BC%D0%BF%D1%81%D0%BE%D0%BD%D0%B0&amp;diff=43456</id>
		<title>Построение по НКА эквивалентного ДКА, алгоритм Томпсона</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE_%D0%9D%D0%9A%D0%90_%D1%8D%D0%BA%D0%B2%D0%B8%D0%B2%D0%B0%D0%BB%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%94%D0%9A%D0%90,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A2%D0%BE%D0%BC%D0%BF%D1%81%D0%BE%D0%BD%D0%B0&amp;diff=43456"/>
				<updated>2015-01-05T14:44:15Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: /* Доказательство эквивалентности */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Описание ==&lt;br /&gt;
Алгоритм Томпсона строит по [[Недетерминированные конечные автоматы|НКА]] эквивалентный [[Детерминированные конечные автоматы|ДКА]] следующим образом:&lt;br /&gt;
* Начало.&lt;br /&gt;
* '''Шаг 1.''' Помещаем в очередь &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; множество, состоящее только из стартовой вершины.&lt;br /&gt;
* '''Шаг 2.''' Затем, пока очередь не пуста выполняем следующие действия:&lt;br /&gt;
** Достаем из очереди множество, назовем его &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt;&lt;br /&gt;
** Для каждого &amp;lt;tex&amp;gt;c \in \Sigma&amp;lt;/tex&amp;gt; построим множество, содержащее состояния, в которые ведет символ &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; из каждого состояния из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt;. Затем положим построенное множество в очередь &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; только если оно не лежало там раньше. Каждое такое множество в итоговом ДКА будет отдельной вершиной, в которую будут вести переходы по соответствующим символам.&lt;br /&gt;
** Если в множестве &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; хотя бы одна из вершин была терминальной в НКА, то соответствующая данному множеству вершина в ДКА также будет терминальной.&lt;br /&gt;
* Конец.&lt;br /&gt;
&lt;br /&gt;
== Построение эквивалентного ДКА по НКА ==&lt;br /&gt;
&lt;br /&gt;
Пусть нам дан произвольный НКА: &amp;lt;tex&amp;gt;\langle \Sigma , Q, s \in Q, T \subset Q, \delta : Q \times \Sigma \to 2^Q \rangle&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Построим по нему следующий ДКА: &amp;lt;tex&amp;gt;\langle \Sigma , Q_d, s_d \in Q_d, T_d \subset Q_d, \delta_d : Q_d \times \Sigma \to Q_d \rangle&amp;lt;/tex&amp;gt;, где:&lt;br /&gt;
# &amp;lt;tex&amp;gt;Q_d = \{q_d \mid q_d \subset 2^Q \}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;s_d = \{s\}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;T_d = \{q \in Q_d \mid \exists p \in T : p \in q\}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;\delta_d(q, c) = \{ \delta(a, c) \mid a \in q \}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Доказательство эквивалентности===&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
Построенный ДКА эквивалентен данному НКА.&lt;br /&gt;
|proof=&lt;br /&gt;
#Докажем, что любое слово, которое принимает НКА, будет принято построенным ДКА. Заметим, что &amp;lt;tex&amp;gt;\forall q \in q_d, \forall c \in \Sigma, \forall p \in \delta(q, c): p \in \delta_d(q_d, c)&amp;lt;/tex&amp;gt;. Рассмотрим слово &amp;lt;tex&amp;gt;w=w_1 \dots w_m&amp;lt;/tex&amp;gt;, которое принимает автомат НКА: &amp;lt;tex&amp;gt;\langle s, w_1w_2 \dots w_m \rangle \vdash \langle u_1, w_2 \dots w_m \rangle \vdash \langle u_m, \varepsilon \rangle, u_m \in T&amp;lt;/tex&amp;gt;. Проверим, что построенный ДКА тоже принимает это слово. Заметим, что &amp;lt;tex&amp;gt;s \in s_d&amp;lt;/tex&amp;gt;, а, значит, исходя из нашего наблюдения, мы получаем, что &amp;lt;tex&amp;gt;u_1 \in {u_d}_1&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;{u_d}_1 = \delta_d(s, w_1)&amp;lt;/tex&amp;gt;. Далее, несложно заметить, что &amp;lt;tex&amp;gt;\forall i \leqslant m : u_i \in {u_d}_i&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\langle s_d, w_1w_2 \dots w_m \rangle \vdash \langle {u_d}_1, w_2 \dots w_m \rangle \vdash \langle {u_d}_i, w_{i + 1} \dots w_m\rangle&amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;tex&amp;gt;u_m \in {u_d}_m&amp;lt;/tex&amp;gt;, а из определения терминальных состояний в построенном ДКА мы получаем, что &amp;lt;tex&amp;gt;{u_d}_m \in T_d&amp;lt;/tex&amp;gt;, то есть наш ДКА тоже принимает cлово &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Докажем, что любое слово, которое принимает построенный ДКА, принимает и НКА. Сначала сделаем наблюдение, что если &amp;lt;tex&amp;gt;q_d=\{q\}&amp;lt;/tex&amp;gt;, и мы из него достигли по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; какого-то состояния &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\forall p \in p_d&amp;lt;/tex&amp;gt; существует путь из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; в НКА по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим слово &amp;lt;tex&amp;gt;w=w_1 \dots w_m&amp;lt;/tex&amp;gt;, которое принимает автомат ДКА: &amp;lt;tex&amp;gt;\langle s_d, w_1w_2 \dots w_m \rangle \vdash \langle {u_d}_1, w_2 \dots w_m \rangle \vdash \langle {u_d}_m, \varepsilon \rangle, {u_d}_m \in T_d&amp;lt;/tex&amp;gt;. Проверим, что НКА тоже принимает это слово. Так как &amp;lt;tex&amp;gt;s_d = \{s\}&amp;lt;/tex&amp;gt;, и мы из &amp;lt;tex&amp;gt;s_d&amp;lt;/tex&amp;gt; достигли &amp;lt;tex&amp;gt;{u_d}_m \in T_d&amp;lt;/tex&amp;gt;, возьмём любое терминальное состояние &amp;lt;tex&amp;gt;u_m \in {u_d}_m&amp;lt;/tex&amp;gt;. По нашему наблюдению в НКА есть путь из &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;u_m&amp;lt;/tex&amp;gt; по строке &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;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;
&amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; {{---}} очередь состояний, соответствующих множествам, состоящих из состояний НКА.&lt;br /&gt;
&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; {{---}} стартовое состояние НКА.&lt;br /&gt;
 '''Automaton''' getDFAbyNFA(&amp;lt;tex&amp;gt;\langle \Sigma, Q_0, s, T_0, \delta_0 \rangle&amp;lt;/tex&amp;gt; : '''Automaton'''):&lt;br /&gt;
   &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.push({s})&lt;br /&gt;
   '''while''' (&amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt; \neq &amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\varnothing &amp;lt;/tex&amp;gt;)&lt;br /&gt;
       &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.pop(&amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''for''' (&amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;\Sigma&amp;lt;/tex&amp;gt;)&lt;br /&gt;
           &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;\varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
           '''for''' (&amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt;) &lt;br /&gt;
              &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;p_d \cup \{ \delta_0(q, c) \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
           '''if''' ('''not''' visited[&amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;])&lt;br /&gt;
              &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;)&lt;br /&gt;
              &amp;lt;tex&amp;gt;\delta(q_d, p_d)&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;&lt;br /&gt;
              '''if''' (&amp;lt;tex&amp;gt;\exists q&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;q_d: q&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;T_0&amp;lt;/tex&amp;gt;)&lt;br /&gt;
                 &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;.add&amp;lt;tex&amp;gt;(q_d)&amp;lt;/tex&amp;gt;&lt;br /&gt;
   '''return''' &amp;lt;tex&amp;gt;\langle \Sigma, Q, \{s\}, T, \delta \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Асимптотика===&lt;br /&gt;
Так как количество подмножеств множества состояний НКА не более, чем &amp;lt;tex&amp;gt;2^n&amp;lt;/tex&amp;gt;, а каждое подмножество мы обрабатываем ровно один раз за время &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;, получаем верхнюю оценку времени работы алгоритма {{---}} &amp;lt;tex&amp;gt;O(n \cdot 2^n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
Пусть нам дан [[Недетерминированные конечные автоматы|недетерминированный конечный автомат]]: &lt;br /&gt;
&lt;br /&gt;
[[Файл:DKA.png|250px]]&lt;br /&gt;
&lt;br /&gt;
По нашему заданию эквивалентного ДКА мы получаем: &lt;br /&gt;
&lt;br /&gt;
[[Файл:NKA_definition.png|250px]]&lt;br /&gt;
&lt;br /&gt;
#Помещаем в очередь множество из одной стартовой вершины — &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\{1\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Достаём из очереди множество &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1\}, a) = \{1, 2\}&amp;lt;/tex&amp;gt;, кладём множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь: &amp;lt;tex&amp;gt;Q = \{\{1, 2\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1\}, b) = \{1\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#Достаём из очереди множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1, 2\}, a) = \{1, 2\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1, 2\}, b) = \{1, 2\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#Помечаем все терминальные вершины, в данном случае — &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем ДКА, эквивалентный исходному: &lt;br /&gt;
&lt;br /&gt;
[[Файл:NKA_algorithm.png|250px]].&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
&lt;br /&gt;
* [[Регулярные языки: два определения и их эквивалентность]]&lt;br /&gt;
* [[Минимизация ДКА, алгоритм за O(n^2) с построением пар различимых состояний]]&lt;br /&gt;
* [[Теорема Клини (совпадение классов автоматных и регулярных языков)]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* ''Серебряков В.А.'' Теория и реализация языков программирования. М.: МЗ-Пресс, 2003 (1-е изд.) и 2006 (2-е изд) — С. 294. — ISBN 5-94073-094-9&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Автоматы и регулярные языки]]&lt;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE_%D0%9D%D0%9A%D0%90_%D1%8D%D0%BA%D0%B2%D0%B8%D0%B2%D0%B0%D0%BB%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%94%D0%9A%D0%90,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A2%D0%BE%D0%BC%D0%BF%D1%81%D0%BE%D0%BD%D0%B0&amp;diff=43455</id>
		<title>Построение по НКА эквивалентного ДКА, алгоритм Томпсона</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE_%D0%9D%D0%9A%D0%90_%D1%8D%D0%BA%D0%B2%D0%B8%D0%B2%D0%B0%D0%BB%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%94%D0%9A%D0%90,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A2%D0%BE%D0%BC%D0%BF%D1%81%D0%BE%D0%BD%D0%B0&amp;diff=43455"/>
				<updated>2015-01-05T14:43:31Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: /* Описание */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Описание ==&lt;br /&gt;
Алгоритм Томпсона строит по [[Недетерминированные конечные автоматы|НКА]] эквивалентный [[Детерминированные конечные автоматы|ДКА]] следующим образом:&lt;br /&gt;
* Начало.&lt;br /&gt;
* '''Шаг 1.''' Помещаем в очередь &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; множество, состоящее только из стартовой вершины.&lt;br /&gt;
* '''Шаг 2.''' Затем, пока очередь не пуста выполняем следующие действия:&lt;br /&gt;
** Достаем из очереди множество, назовем его &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt;&lt;br /&gt;
** Для каждого &amp;lt;tex&amp;gt;c \in \Sigma&amp;lt;/tex&amp;gt; построим множество, содержащее состояния, в которые ведет символ &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; из каждого состояния из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt;. Затем положим построенное множество в очередь &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; только если оно не лежало там раньше. Каждое такое множество в итоговом ДКА будет отдельной вершиной, в которую будут вести переходы по соответствующим символам.&lt;br /&gt;
** Если в множестве &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; хотя бы одна из вершин была терминальной в НКА, то соответствующая данному множеству вершина в ДКА также будет терминальной.&lt;br /&gt;
* Конец.&lt;br /&gt;
&lt;br /&gt;
== Построение эквивалентного ДКА по НКА ==&lt;br /&gt;
&lt;br /&gt;
Пусть нам дан произвольный НКА: &amp;lt;tex&amp;gt;\langle \Sigma , Q, s \in Q, T \subset Q, \delta : Q \times \Sigma \to 2^Q \rangle&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Построим по нему следующий ДКА: &amp;lt;tex&amp;gt;\langle \Sigma , Q_d, s_d \in Q_d, T_d \subset Q_d, \delta_d : Q_d \times \Sigma \to Q_d \rangle&amp;lt;/tex&amp;gt;, где:&lt;br /&gt;
# &amp;lt;tex&amp;gt;Q_d = \{q_d \mid q_d \subset 2^Q \}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;s_d = \{s\}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;T_d = \{q \in Q_d \mid \exists p \in T : p \in q\}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;\delta_d(q, c) = \{ \delta(a, c) \mid a \in q \}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Доказательство эквивалентности===&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
Построенный ДКА эквивалентен данному НКА.&lt;br /&gt;
|proof=&lt;br /&gt;
#Докажем, что любое слово, которое принимает НКА, будет принято построенным ДКА. Заметим, что &amp;lt;tex&amp;gt;\forall q \in q_d, \forall c \in \Sigma, \forall p \in \delta(q, c): p \in \delta_d(q_d, c)&amp;lt;/tex&amp;gt;. Рассмотрим слово &amp;lt;tex&amp;gt;w=w_1...w_m&amp;lt;/tex&amp;gt;, которое принимает автомат НКА: &amp;lt;tex&amp;gt;\langle s, w_1w_2 \dots w_m \rangle \vdash \langle u_1, w_2 \dots w_m \rangle \vdash \langle u_m, \varepsilon \rangle, u_m \in T&amp;lt;/tex&amp;gt;. Проверим, что построенный ДКА тоже принимает это слово. Заметим, что &amp;lt;tex&amp;gt;s \in s_d&amp;lt;/tex&amp;gt;, а, значит, исходя из нашего наблюдения, мы получаем, что &amp;lt;tex&amp;gt;u_1 \in {u_d}_1&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;{u_d}_1 = \delta_d(s, w_1)&amp;lt;/tex&amp;gt;. Далее, несложно заметить, что &amp;lt;tex&amp;gt;\forall i \leqslant m : u_i \in {u_d}_i&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\langle s_d, w_1w_2 \dots w_m \rangle \vdash \langle {u_d}_1, w_2 \dots w_m \rangle \vdash \langle {u_d}_i, w_{i + 1} \dots w_m\rangle&amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;tex&amp;gt;u_m \in {u_d}_m&amp;lt;/tex&amp;gt;, а из определения терминальных состояний в построенном ДКА мы получаем, что &amp;lt;tex&amp;gt;{u_d}_m \in T_d&amp;lt;/tex&amp;gt;, то есть наш ДКА тоже принимает cлово &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Докажем, что любое слово, которое принимает построенный ДКА, принимает и НКА. Сначала сделаем наблюдение, что если &amp;lt;tex&amp;gt;q_d=\{q\}&amp;lt;/tex&amp;gt;, и мы из него достигли по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; какого-то состояния &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\forall p \in p_d&amp;lt;/tex&amp;gt; существует путь из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; в НКА по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим слово &amp;lt;tex&amp;gt;w=w_1 \dots w_m&amp;lt;/tex&amp;gt;, которое принимает автомат ДКА: &amp;lt;tex&amp;gt;\langle s_d, w_1w_2 \dots w_m \rangle \vdash \langle {u_d}_1, w_2 \dots w_m \rangle \vdash \langle {u_d}_m, \varepsilon \rangle, {u_d}_m \in T_d&amp;lt;/tex&amp;gt;. Проверим, что НКА тоже принимает это слово. Так как &amp;lt;tex&amp;gt;s_d = \{s\}&amp;lt;/tex&amp;gt;, и мы из &amp;lt;tex&amp;gt;s_d&amp;lt;/tex&amp;gt; достигли &amp;lt;tex&amp;gt;{u_d}_m \in T_d&amp;lt;/tex&amp;gt;, возьмём любое терминальное состояние &amp;lt;tex&amp;gt;u_m \in {u_d}_m&amp;lt;/tex&amp;gt;. По нашему наблюдению в НКА есть путь из &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;u_m&amp;lt;/tex&amp;gt; по строке &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;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;
&amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; {{---}} очередь состояний, соответствующих множествам, состоящих из состояний НКА.&lt;br /&gt;
&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; {{---}} стартовое состояние НКА.&lt;br /&gt;
 '''Automaton''' getDFAbyNFA(&amp;lt;tex&amp;gt;\langle \Sigma, Q_0, s, T_0, \delta_0 \rangle&amp;lt;/tex&amp;gt; : '''Automaton'''):&lt;br /&gt;
   &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.push({s})&lt;br /&gt;
   '''while''' (&amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt; \neq &amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\varnothing &amp;lt;/tex&amp;gt;)&lt;br /&gt;
       &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.pop(&amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''for''' (&amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;\Sigma&amp;lt;/tex&amp;gt;)&lt;br /&gt;
           &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;\varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
           '''for''' (&amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt;) &lt;br /&gt;
              &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;p_d \cup \{ \delta_0(q, c) \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
           '''if''' ('''not''' visited[&amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;])&lt;br /&gt;
              &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;)&lt;br /&gt;
              &amp;lt;tex&amp;gt;\delta(q_d, p_d)&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;&lt;br /&gt;
              '''if''' (&amp;lt;tex&amp;gt;\exists q&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;q_d: q&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;T_0&amp;lt;/tex&amp;gt;)&lt;br /&gt;
                 &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;.add&amp;lt;tex&amp;gt;(q_d)&amp;lt;/tex&amp;gt;&lt;br /&gt;
   '''return''' &amp;lt;tex&amp;gt;\langle \Sigma, Q, \{s\}, T, \delta \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Асимптотика===&lt;br /&gt;
Так как количество подмножеств множества состояний НКА не более, чем &amp;lt;tex&amp;gt;2^n&amp;lt;/tex&amp;gt;, а каждое подмножество мы обрабатываем ровно один раз за время &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;, получаем верхнюю оценку времени работы алгоритма {{---}} &amp;lt;tex&amp;gt;O(n \cdot 2^n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
Пусть нам дан [[Недетерминированные конечные автоматы|недетерминированный конечный автомат]]: &lt;br /&gt;
&lt;br /&gt;
[[Файл:DKA.png|250px]]&lt;br /&gt;
&lt;br /&gt;
По нашему заданию эквивалентного ДКА мы получаем: &lt;br /&gt;
&lt;br /&gt;
[[Файл:NKA_definition.png|250px]]&lt;br /&gt;
&lt;br /&gt;
#Помещаем в очередь множество из одной стартовой вершины — &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\{1\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Достаём из очереди множество &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1\}, a) = \{1, 2\}&amp;lt;/tex&amp;gt;, кладём множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь: &amp;lt;tex&amp;gt;Q = \{\{1, 2\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1\}, b) = \{1\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#Достаём из очереди множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1, 2\}, a) = \{1, 2\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1, 2\}, b) = \{1, 2\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#Помечаем все терминальные вершины, в данном случае — &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем ДКА, эквивалентный исходному: &lt;br /&gt;
&lt;br /&gt;
[[Файл:NKA_algorithm.png|250px]].&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
&lt;br /&gt;
* [[Регулярные языки: два определения и их эквивалентность]]&lt;br /&gt;
* [[Минимизация ДКА, алгоритм за O(n^2) с построением пар различимых состояний]]&lt;br /&gt;
* [[Теорема Клини (совпадение классов автоматных и регулярных языков)]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* ''Серебряков В.А.'' Теория и реализация языков программирования. М.: МЗ-Пресс, 2003 (1-е изд.) и 2006 (2-е изд) — С. 294. — ISBN 5-94073-094-9&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Автоматы и регулярные языки]]&lt;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE_%D0%9D%D0%9A%D0%90_%D1%8D%D0%BA%D0%B2%D0%B8%D0%B2%D0%B0%D0%BB%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%94%D0%9A%D0%90,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A2%D0%BE%D0%BC%D0%BF%D1%81%D0%BE%D0%BD%D0%B0&amp;diff=43447</id>
		<title>Построение по НКА эквивалентного ДКА, алгоритм Томпсона</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE_%D0%9D%D0%9A%D0%90_%D1%8D%D0%BA%D0%B2%D0%B8%D0%B2%D0%B0%D0%BB%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%94%D0%9A%D0%90,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A2%D0%BE%D0%BC%D0%BF%D1%81%D0%BE%D0%BD%D0%B0&amp;diff=43447"/>
				<updated>2015-01-05T07:12:51Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: /* Алгоритм */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Описание ==&lt;br /&gt;
Алгоритм Томпсона строит по [[Недетерминированные конечные автоматы|НКА]] эквивалентный [[Детерминированные конечные автоматы|ДКА]] следующим образом:&lt;br /&gt;
* Начало.&lt;br /&gt;
* '''Шаг 1''' Помещаем в очередь &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; множество, состоящее только из стартовой вершины.&lt;br /&gt;
* '''Шаг 2''' Затем, пока очередь не пуста выполняем следующие действия:&lt;br /&gt;
** Достаем из очереди множество, назовем его &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt;&lt;br /&gt;
** Для каждого &amp;lt;tex&amp;gt;c \in \Sigma&amp;lt;/tex&amp;gt; построим множество, содержащее состояния, в которые ведет символ &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; из каждого состояния из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt;. Затем положим построенное множество в очередь &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; только если оно не лежало там раньше. Каждое такое множество в итоговом ДКА будет отдельной вершиной, в которую будут вести переходы по соответствующим символам.&lt;br /&gt;
** Если в множестве &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; хотя бы одна из вершин была терминальной в НКА, то соответствующая данному множеству вершина в ДКА также будет терминальной.&lt;br /&gt;
* Конец&lt;br /&gt;
&lt;br /&gt;
== Построение эквивалентного ДКА по НКА ==&lt;br /&gt;
&lt;br /&gt;
Пусть нам дан произвольный НКА: &amp;lt;tex&amp;gt;\langle \Sigma , Q, s \in Q, T \subset Q, \delta : Q \times \Sigma \to 2^Q \rangle&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Построим по нему следующий ДКА: &amp;lt;tex&amp;gt;\langle \Sigma , Q_d, s_d \in Q_d, T_d \subset Q_d, \delta_d : Q_d \times \Sigma \to Q_d \rangle&amp;lt;/tex&amp;gt;, где:&lt;br /&gt;
# &amp;lt;tex&amp;gt;Q_d = \{q_d \mid q_d \subset 2^Q \}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;s_d = \{s\}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;T_d = \{q \in Q_d \mid \exists p \in T : p \in q\}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;\delta_d(q, c) = \{ \delta(a, c) \mid a \in q \}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Доказательство эквивалентности===&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
Построенный ДКА эквивалентен данному НКА.&lt;br /&gt;
|proof=&lt;br /&gt;
#Докажем, что любое слово, которое принимает НКА, будет принято построенным ДКА. Заметим, что &amp;lt;tex&amp;gt;\forall q \in q_d, \forall c \in \Sigma, \forall p \in \delta(q, c): p \in \delta_d(q_d, c)&amp;lt;/tex&amp;gt;. Рассмотрим слово &amp;lt;tex&amp;gt;w=w_1...w_m&amp;lt;/tex&amp;gt;, которое принимает автомат НКА: &amp;lt;tex&amp;gt;\langle s, w_1w_2 \dots w_m \rangle \vdash \langle u_1, w_2 \dots w_m \rangle \vdash \langle u_m, \varepsilon \rangle, u_m \in T&amp;lt;/tex&amp;gt;. Проверим, что построенный ДКА тоже принимает это слово. Заметим, что &amp;lt;tex&amp;gt;s \in s_d&amp;lt;/tex&amp;gt;, а, значит, исходя из нашего наблюдения, мы получаем, что &amp;lt;tex&amp;gt;u_1 \in {u_d}_1&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;{u_d}_1 = \delta_d(s, w_1)&amp;lt;/tex&amp;gt;. Далее, несложно заметить, что &amp;lt;tex&amp;gt;\forall i \leqslant m : u_i \in {u_d}_i&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\langle s_d, w_1w_2 \dots w_m \rangle \vdash \langle {u_d}_1, w_2 \dots w_m \rangle \vdash \langle {u_d}_i, w_{i + 1} \dots w_m\rangle&amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;tex&amp;gt;u_m \in {u_d}_m&amp;lt;/tex&amp;gt;, а из определения терминальных состояний в построенном ДКА мы получаем, что &amp;lt;tex&amp;gt;{u_d}_m \in T_d&amp;lt;/tex&amp;gt;, то есть наш ДКА тоже принимает cлово &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Докажем, что любое слово, которое принимает построенный ДКА, принимает и НКА. Сначала сделаем наблюдение, что если &amp;lt;tex&amp;gt;q_d=\{q\}&amp;lt;/tex&amp;gt;, и мы из него достигли по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; какого-то состояния &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\forall p \in p_d&amp;lt;/tex&amp;gt; существует путь из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; в НКА по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим слово &amp;lt;tex&amp;gt;w=w_1 \dots w_m&amp;lt;/tex&amp;gt;, которое принимает автомат ДКА: &amp;lt;tex&amp;gt;\langle s_d, w_1w_2 \dots w_m \rangle \vdash \langle {u_d}_1, w_2 \dots w_m \rangle \vdash \langle {u_d}_m, \varepsilon \rangle, {u_d}_m \in T_d&amp;lt;/tex&amp;gt;. Проверим, что НКА тоже принимает это слово. Так как &amp;lt;tex&amp;gt;s_d = \{s\}&amp;lt;/tex&amp;gt;, и мы из &amp;lt;tex&amp;gt;s_d&amp;lt;/tex&amp;gt; достигли &amp;lt;tex&amp;gt;{u_d}_m \in T_d&amp;lt;/tex&amp;gt;, возьмём любое терминальное состояние &amp;lt;tex&amp;gt;u_m \in {u_d}_m&amp;lt;/tex&amp;gt;. По нашему наблюдению в НКА есть путь из &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;u_m&amp;lt;/tex&amp;gt; по строке &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;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;
&amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; {{---}} очередь состояний, соответствующих множествам, состоящих из состояний НКА.&lt;br /&gt;
&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; {{---}} стартовое состояние НКА.&lt;br /&gt;
 '''Automaton''' getDFAbyNFA(&amp;lt;tex&amp;gt;\langle \Sigma, Q_0, s, T_0, \delta_0 \rangle&amp;lt;/tex&amp;gt; : '''Automaton'''):&lt;br /&gt;
   &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.push({s})&lt;br /&gt;
   '''while''' (&amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt; \neq &amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\varnothing &amp;lt;/tex&amp;gt;)&lt;br /&gt;
       &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.pop(&amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''for''' (&amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;\Sigma&amp;lt;/tex&amp;gt;)&lt;br /&gt;
           &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;\varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
           '''for''' (&amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt;) &lt;br /&gt;
              &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;p_d \cup \{ \delta_0(q, c) \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
           '''if''' ('''not''' visited[&amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;])&lt;br /&gt;
              &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;)&lt;br /&gt;
              &amp;lt;tex&amp;gt;\delta(q_d, p_d)&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;&lt;br /&gt;
              '''if''' (&amp;lt;tex&amp;gt;\exists q&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;q_d: q&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;T_0&amp;lt;/tex&amp;gt;)&lt;br /&gt;
                 &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;.add&amp;lt;tex&amp;gt;(q_d)&amp;lt;/tex&amp;gt;&lt;br /&gt;
   '''return''' &amp;lt;tex&amp;gt;\langle \Sigma, Q, \{s\}, T, \delta \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Асимптотика===&lt;br /&gt;
Так как количество подмножеств множества состояний НКА не более, чем &amp;lt;tex&amp;gt;2^n&amp;lt;/tex&amp;gt;, а каждое подмножество мы обрабатываем ровно один раз за время &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;, получаем верхнюю оценку времени работы алгоритма {{---}} &amp;lt;tex&amp;gt;O(n \cdot 2^n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
Пусть нам дан [[Недетерминированные конечные автоматы|недетерминированный конечный автомат]]: &lt;br /&gt;
&lt;br /&gt;
[[Файл:DKA.png|250px]]&lt;br /&gt;
&lt;br /&gt;
По нашему заданию эквивалентного ДКА мы получаем: &lt;br /&gt;
&lt;br /&gt;
[[Файл:NKA_definition.png|250px]]&lt;br /&gt;
&lt;br /&gt;
#Помещаем в очередь множество из одной стартовой вершины — &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\{1\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Достаём из очереди множество &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1\}, a) = \{1, 2\}&amp;lt;/tex&amp;gt;, кладём множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь: &amp;lt;tex&amp;gt;Q = \{\{1, 2\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1\}, b) = \{1\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#Достаём из очереди множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1, 2\}, a) = \{1, 2\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1, 2\}, b) = \{1, 2\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#Помечаем все терминальные вершины, в данном случае — &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем ДКА, эквивалентный исходному: &lt;br /&gt;
&lt;br /&gt;
[[Файл:NKA_algorithm.png|250px]].&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
&lt;br /&gt;
* [[Регулярные языки: два определения и их эквивалентность]]&lt;br /&gt;
* [[Минимизация ДКА, алгоритм за O(n^2) с построением пар различимых состояний]]&lt;br /&gt;
* [[Теорема Клини (совпадение классов автоматных и регулярных языков)]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* ''Серебряков В.А.'' Теория и реализация языков программирования. М.: МЗ-Пресс, 2003 (1-е изд.) и 2006 (2-е изд) — С. 294. — ISBN 5-94073-094-9&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Автоматы и регулярные языки]]&lt;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE_%D0%9D%D0%9A%D0%90_%D1%8D%D0%BA%D0%B2%D0%B8%D0%B2%D0%B0%D0%BB%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%94%D0%9A%D0%90,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A2%D0%BE%D0%BC%D0%BF%D1%81%D0%BE%D0%BD%D0%B0&amp;diff=43446</id>
		<title>Построение по НКА эквивалентного ДКА, алгоритм Томпсона</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE_%D0%9D%D0%9A%D0%90_%D1%8D%D0%BA%D0%B2%D0%B8%D0%B2%D0%B0%D0%BB%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%94%D0%9A%D0%90,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A2%D0%BE%D0%BC%D0%BF%D1%81%D0%BE%D0%BD%D0%B0&amp;diff=43446"/>
				<updated>2015-01-05T06:50:30Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: /* См. также */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Описание ==&lt;br /&gt;
Алгоритм Томпсона строит по [[Недетерминированные конечные автоматы|НКА]] эквивалентный [[Детерминированные конечные автоматы|ДКА]] следующим образом:&lt;br /&gt;
* Начало.&lt;br /&gt;
* '''Шаг 1''' Помещаем в очередь &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; множество, состоящее только из стартовой вершины.&lt;br /&gt;
* '''Шаг 2''' Затем, пока очередь не пуста выполняем следующие действия:&lt;br /&gt;
** Достаем из очереди множество, назовем его &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt;&lt;br /&gt;
** Для каждого &amp;lt;tex&amp;gt;c \in \Sigma&amp;lt;/tex&amp;gt; построим множество, содержащее состояния, в которые ведет символ &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; из каждого состояния из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt;. Затем положим построенное множество в очередь &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; только если оно не лежало там раньше. Каждое такое множество в итоговом ДКА будет отдельной вершиной, в которую будут вести переходы по соответствующим символам.&lt;br /&gt;
** Если в множестве &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; хотя бы одна из вершин была терминальной в НКА, то соответствующая данному множеству вершина в ДКА также будет терминальной.&lt;br /&gt;
* Конец&lt;br /&gt;
&lt;br /&gt;
== Построение эквивалентного ДКА по НКА ==&lt;br /&gt;
&lt;br /&gt;
Пусть нам дан произвольный НКА: &amp;lt;tex&amp;gt;\langle \Sigma , Q, s \in Q, T \subset Q, \delta : Q \times \Sigma \to 2^Q \rangle&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Построим по нему следующий ДКА: &amp;lt;tex&amp;gt;\langle \Sigma , Q_d, s_d \in Q_d, T_d \subset Q_d, \delta_d : Q_d \times \Sigma \to Q_d \rangle&amp;lt;/tex&amp;gt;, где:&lt;br /&gt;
# &amp;lt;tex&amp;gt;Q_d = \{q_d \mid q_d \subset 2^Q \}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;s_d = \{s\}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;T_d = \{q \in Q_d \mid \exists p \in T : p \in q\}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;\delta_d(q, c) = \{ \delta(a, c) \mid a \in q \}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Доказательство эквивалентности===&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
Построенный ДКА эквивалентен данному НКА.&lt;br /&gt;
|proof=&lt;br /&gt;
#Докажем, что любое слово, которое принимает НКА, будет принято построенным ДКА. Заметим, что &amp;lt;tex&amp;gt;\forall q \in q_d, \forall c \in \Sigma, \forall p \in \delta(q, c): p \in \delta_d(q_d, c)&amp;lt;/tex&amp;gt;. Рассмотрим слово &amp;lt;tex&amp;gt;w=w_1...w_m&amp;lt;/tex&amp;gt;, которое принимает автомат НКА: &amp;lt;tex&amp;gt;\langle s, w_1w_2 \dots w_m \rangle \vdash \langle u_1, w_2 \dots w_m \rangle \vdash \langle u_m, \varepsilon \rangle, u_m \in T&amp;lt;/tex&amp;gt;. Проверим, что построенный ДКА тоже принимает это слово. Заметим, что &amp;lt;tex&amp;gt;s \in s_d&amp;lt;/tex&amp;gt;, а, значит, исходя из нашего наблюдения, мы получаем, что &amp;lt;tex&amp;gt;u_1 \in {u_d}_1&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;{u_d}_1 = \delta_d(s, w_1)&amp;lt;/tex&amp;gt;. Далее, несложно заметить, что &amp;lt;tex&amp;gt;\forall i \leqslant m : u_i \in {u_d}_i&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\langle s_d, w_1w_2 \dots w_m \rangle \vdash \langle {u_d}_1, w_2 \dots w_m \rangle \vdash \langle {u_d}_i, w_{i + 1} \dots w_m\rangle&amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;tex&amp;gt;u_m \in {u_d}_m&amp;lt;/tex&amp;gt;, а из определения терминальных состояний в построенном ДКА мы получаем, что &amp;lt;tex&amp;gt;{u_d}_m \in T_d&amp;lt;/tex&amp;gt;, то есть наш ДКА тоже принимает cлово &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Докажем, что любое слово, которое принимает построенный ДКА, принимает и НКА. Сначала сделаем наблюдение, что если &amp;lt;tex&amp;gt;q_d=\{q\}&amp;lt;/tex&amp;gt;, и мы из него достигли по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; какого-то состояния &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\forall p \in p_d&amp;lt;/tex&amp;gt; существует путь из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; в НКА по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим слово &amp;lt;tex&amp;gt;w=w_1 \dots w_m&amp;lt;/tex&amp;gt;, которое принимает автомат ДКА: &amp;lt;tex&amp;gt;\langle s_d, w_1w_2 \dots w_m \rangle \vdash \langle {u_d}_1, w_2 \dots w_m \rangle \vdash \langle {u_d}_m, \varepsilon \rangle, {u_d}_m \in T_d&amp;lt;/tex&amp;gt;. Проверим, что НКА тоже принимает это слово. Так как &amp;lt;tex&amp;gt;s_d = \{s\}&amp;lt;/tex&amp;gt;, и мы из &amp;lt;tex&amp;gt;s_d&amp;lt;/tex&amp;gt; достигли &amp;lt;tex&amp;gt;{u_d}_m \in T_d&amp;lt;/tex&amp;gt;, возьмём любое терминальное состояние &amp;lt;tex&amp;gt;u_m \in {u_d}_m&amp;lt;/tex&amp;gt;. По нашему наблюдению в НКА есть путь из &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;u_m&amp;lt;/tex&amp;gt; по строке &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;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;
&amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; {{---}} очередь состояний, соответствующих множествам, состоящих из состояний НКА.&lt;br /&gt;
&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; {{---}} стартовое состояние НКА.&lt;br /&gt;
 '''Automaton''' getDFAbyNFA(&amp;lt;tex&amp;gt;\langle \Sigma, Q_0, s, T, \delta_0 \rangle&amp;lt;/tex&amp;gt; : '''Automaton'''):&lt;br /&gt;
   &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.push({s})&lt;br /&gt;
   '''while''' (&amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt; \neq &amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\varnothing &amp;lt;/tex&amp;gt;)&lt;br /&gt;
       &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.pop(&amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''for''' (&amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;\Sigma&amp;lt;/tex&amp;gt;)&lt;br /&gt;
           &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;\varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
           '''for''' (&amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt;) &lt;br /&gt;
              &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;p_d \cup \{ \delta_0(q, c) \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
           '''if''' ('''not''' visited[&amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;])&lt;br /&gt;
              &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;)&lt;br /&gt;
   '''return''' &amp;lt;tex&amp;gt;\langle \Sigma, Q, s, T, \delta \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Асимптотика===&lt;br /&gt;
Так как количество подмножеств множества состояний НКА не более, чем &amp;lt;tex&amp;gt;2^n&amp;lt;/tex&amp;gt;, а каждое подмножество мы обрабатываем ровно один раз за время &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;, получаем верхнюю оценку времени работы алгоритма {{---}} &amp;lt;tex&amp;gt;O(n \cdot 2^n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
Пусть нам дан [[Недетерминированные конечные автоматы|недетерминированный конечный автомат]]: &lt;br /&gt;
&lt;br /&gt;
[[Файл:DKA.png|250px]]&lt;br /&gt;
&lt;br /&gt;
По нашему заданию эквивалентного ДКА мы получаем: &lt;br /&gt;
&lt;br /&gt;
[[Файл:NKA_definition.png|250px]]&lt;br /&gt;
&lt;br /&gt;
#Помещаем в очередь множество из одной стартовой вершины — &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\{1\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Достаём из очереди множество &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1\}, a) = \{1, 2\}&amp;lt;/tex&amp;gt;, кладём множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь: &amp;lt;tex&amp;gt;Q = \{\{1, 2\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1\}, b) = \{1\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#Достаём из очереди множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1, 2\}, a) = \{1, 2\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1, 2\}, b) = \{1, 2\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#Помечаем все терминальные вершины, в данном случае — &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем ДКА, эквивалентный исходному: &lt;br /&gt;
&lt;br /&gt;
[[Файл:NKA_algorithm.png|250px]].&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
&lt;br /&gt;
* [[Регулярные языки: два определения и их эквивалентность]]&lt;br /&gt;
* [[Минимизация ДКА, алгоритм за O(n^2) с построением пар различимых состояний]]&lt;br /&gt;
* [[Теорема Клини (совпадение классов автоматных и регулярных языков)]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* ''Серебряков В.А.'' Теория и реализация языков программирования. М.: МЗ-Пресс, 2003 (1-е изд.) и 2006 (2-е изд) — С. 294. — ISBN 5-94073-094-9&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Автоматы и регулярные языки]]&lt;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE_%D0%9D%D0%9A%D0%90_%D1%8D%D0%BA%D0%B2%D0%B8%D0%B2%D0%B0%D0%BB%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%94%D0%9A%D0%90,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A2%D0%BE%D0%BC%D0%BF%D1%81%D0%BE%D0%BD%D0%B0&amp;diff=43445</id>
		<title>Построение по НКА эквивалентного ДКА, алгоритм Томпсона</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE_%D0%9D%D0%9A%D0%90_%D1%8D%D0%BA%D0%B2%D0%B8%D0%B2%D0%B0%D0%BB%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%94%D0%9A%D0%90,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A2%D0%BE%D0%BC%D0%BF%D1%81%D0%BE%D0%BD%D0%B0&amp;diff=43445"/>
				<updated>2015-01-05T06:40:41Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: /* См. также */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Описание ==&lt;br /&gt;
Алгоритм Томпсона строит по [[Недетерминированные конечные автоматы|НКА]] эквивалентный [[Детерминированные конечные автоматы|ДКА]] следующим образом:&lt;br /&gt;
* Начало.&lt;br /&gt;
* '''Шаг 1''' Помещаем в очередь &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; множество, состоящее только из стартовой вершины.&lt;br /&gt;
* '''Шаг 2''' Затем, пока очередь не пуста выполняем следующие действия:&lt;br /&gt;
** Достаем из очереди множество, назовем его &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt;&lt;br /&gt;
** Для каждого &amp;lt;tex&amp;gt;c \in \Sigma&amp;lt;/tex&amp;gt; построим множество, содержащее состояния, в которые ведет символ &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; из каждого состояния из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt;. Затем положим построенное множество в очередь &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; только если оно не лежало там раньше. Каждое такое множество в итоговом ДКА будет отдельной вершиной, в которую будут вести переходы по соответствующим символам.&lt;br /&gt;
** Если в множестве &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; хотя бы одна из вершин была терминальной в НКА, то соответствующая данному множеству вершина в ДКА также будет терминальной.&lt;br /&gt;
* Конец&lt;br /&gt;
&lt;br /&gt;
== Построение эквивалентного ДКА по НКА ==&lt;br /&gt;
&lt;br /&gt;
Пусть нам дан произвольный НКА: &amp;lt;tex&amp;gt;\langle \Sigma , Q, s \in Q, T \subset Q, \delta : Q \times \Sigma \to 2^Q \rangle&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Построим по нему следующий ДКА: &amp;lt;tex&amp;gt;\langle \Sigma , Q_d, s_d \in Q_d, T_d \subset Q_d, \delta_d : Q_d \times \Sigma \to Q_d \rangle&amp;lt;/tex&amp;gt;, где:&lt;br /&gt;
# &amp;lt;tex&amp;gt;Q_d = \{q_d \mid q_d \subset 2^Q \}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;s_d = \{s\}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;T_d = \{q \in Q_d \mid \exists p \in T : p \in q\}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;\delta_d(q, c) = \{ \delta(a, c) \mid a \in q \}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Доказательство эквивалентности===&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
Построенный ДКА эквивалентен данному НКА.&lt;br /&gt;
|proof=&lt;br /&gt;
#Докажем, что любое слово, которое принимает НКА, будет принято построенным ДКА. Заметим, что &amp;lt;tex&amp;gt;\forall q \in q_d, \forall c \in \Sigma, \forall p \in \delta(q, c): p \in \delta_d(q_d, c)&amp;lt;/tex&amp;gt;. Рассмотрим слово &amp;lt;tex&amp;gt;w=w_1...w_m&amp;lt;/tex&amp;gt;, которое принимает автомат НКА: &amp;lt;tex&amp;gt;\langle s, w_1w_2 \dots w_m \rangle \vdash \langle u_1, w_2 \dots w_m \rangle \vdash \langle u_m, \varepsilon \rangle, u_m \in T&amp;lt;/tex&amp;gt;. Проверим, что построенный ДКА тоже принимает это слово. Заметим, что &amp;lt;tex&amp;gt;s \in s_d&amp;lt;/tex&amp;gt;, а, значит, исходя из нашего наблюдения, мы получаем, что &amp;lt;tex&amp;gt;u_1 \in {u_d}_1&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;{u_d}_1 = \delta_d(s, w_1)&amp;lt;/tex&amp;gt;. Далее, несложно заметить, что &amp;lt;tex&amp;gt;\forall i \leqslant m : u_i \in {u_d}_i&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\langle s_d, w_1w_2 \dots w_m \rangle \vdash \langle {u_d}_1, w_2 \dots w_m \rangle \vdash \langle {u_d}_i, w_{i + 1} \dots w_m\rangle&amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;tex&amp;gt;u_m \in {u_d}_m&amp;lt;/tex&amp;gt;, а из определения терминальных состояний в построенном ДКА мы получаем, что &amp;lt;tex&amp;gt;{u_d}_m \in T_d&amp;lt;/tex&amp;gt;, то есть наш ДКА тоже принимает cлово &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Докажем, что любое слово, которое принимает построенный ДКА, принимает и НКА. Сначала сделаем наблюдение, что если &amp;lt;tex&amp;gt;q_d=\{q\}&amp;lt;/tex&amp;gt;, и мы из него достигли по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; какого-то состояния &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\forall p \in p_d&amp;lt;/tex&amp;gt; существует путь из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; в НКА по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим слово &amp;lt;tex&amp;gt;w=w_1 \dots w_m&amp;lt;/tex&amp;gt;, которое принимает автомат ДКА: &amp;lt;tex&amp;gt;\langle s_d, w_1w_2 \dots w_m \rangle \vdash \langle {u_d}_1, w_2 \dots w_m \rangle \vdash \langle {u_d}_m, \varepsilon \rangle, {u_d}_m \in T_d&amp;lt;/tex&amp;gt;. Проверим, что НКА тоже принимает это слово. Так как &amp;lt;tex&amp;gt;s_d = \{s\}&amp;lt;/tex&amp;gt;, и мы из &amp;lt;tex&amp;gt;s_d&amp;lt;/tex&amp;gt; достигли &amp;lt;tex&amp;gt;{u_d}_m \in T_d&amp;lt;/tex&amp;gt;, возьмём любое терминальное состояние &amp;lt;tex&amp;gt;u_m \in {u_d}_m&amp;lt;/tex&amp;gt;. По нашему наблюдению в НКА есть путь из &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;u_m&amp;lt;/tex&amp;gt; по строке &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;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;
&amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; {{---}} очередь состояний, соответствующих множествам, состоящих из состояний НКА.&lt;br /&gt;
&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; {{---}} стартовое состояние НКА.&lt;br /&gt;
 '''Automaton''' getDFAbyNFA(&amp;lt;tex&amp;gt;\langle \Sigma, Q_0, s, T, \delta_0 \rangle&amp;lt;/tex&amp;gt; : '''Automaton'''):&lt;br /&gt;
   &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.push({s})&lt;br /&gt;
   '''while''' (&amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt; \neq &amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\varnothing &amp;lt;/tex&amp;gt;)&lt;br /&gt;
       &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.pop(&amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''for''' (&amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;\Sigma&amp;lt;/tex&amp;gt;)&lt;br /&gt;
           &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;\varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
           '''for''' (&amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt;) &lt;br /&gt;
              &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;p_d \cup \{ \delta_0(q, c) \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
           '''if''' ('''not''' visited[&amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;])&lt;br /&gt;
              &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;)&lt;br /&gt;
   '''return''' &amp;lt;tex&amp;gt;\langle \Sigma, Q, s, T, \delta \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Асимптотика===&lt;br /&gt;
Так как количество подмножеств множества состояний НКА не более, чем &amp;lt;tex&amp;gt;2^n&amp;lt;/tex&amp;gt;, а каждое подмножество мы обрабатываем ровно один раз за время &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;, получаем верхнюю оценку времени работы алгоритма {{---}} &amp;lt;tex&amp;gt;O(n \cdot 2^n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
Пусть нам дан [[Недетерминированные конечные автоматы|недетерминированный конечный автомат]]: &lt;br /&gt;
&lt;br /&gt;
[[Файл:DKA.png|250px]]&lt;br /&gt;
&lt;br /&gt;
По нашему заданию эквивалентного ДКА мы получаем: &lt;br /&gt;
&lt;br /&gt;
[[Файл:NKA_definition.png|250px]]&lt;br /&gt;
&lt;br /&gt;
#Помещаем в очередь множество из одной стартовой вершины — &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\{1\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Достаём из очереди множество &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1\}, a) = \{1, 2\}&amp;lt;/tex&amp;gt;, кладём множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь: &amp;lt;tex&amp;gt;Q = \{\{1, 2\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1\}, b) = \{1\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#Достаём из очереди множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1, 2\}, a) = \{1, 2\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1, 2\}, b) = \{1, 2\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#Помечаем все терминальные вершины, в данном случае — &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем ДКА, эквивалентный исходному: &lt;br /&gt;
&lt;br /&gt;
[[Файл:NKA_algorithm.png|250px]].&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
&lt;br /&gt;
* [[Регулярные языки: два определения и их эквивалентность]]&lt;br /&gt;
* [[Минимизация ДКА, алгоритм за O(n^2) с построением пар различимых состояний]]&lt;br /&gt;
* [[Теорема Клини (совпадение классов автоматных и регулярных языков)]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Автоматы и регулярные языки]]&lt;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE_%D0%9D%D0%9A%D0%90_%D1%8D%D0%BA%D0%B2%D0%B8%D0%B2%D0%B0%D0%BB%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%94%D0%9A%D0%90,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A2%D0%BE%D0%BC%D0%BF%D1%81%D0%BE%D0%BD%D0%B0&amp;diff=43444</id>
		<title>Построение по НКА эквивалентного ДКА, алгоритм Томпсона</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE_%D0%9D%D0%9A%D0%90_%D1%8D%D0%BA%D0%B2%D0%B8%D0%B2%D0%B0%D0%BB%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%94%D0%9A%D0%90,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A2%D0%BE%D0%BC%D0%BF%D1%81%D0%BE%D0%BD%D0%B0&amp;diff=43444"/>
				<updated>2015-01-05T06:34:43Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: /* Пример */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Описание ==&lt;br /&gt;
Алгоритм Томпсона строит по [[Недетерминированные конечные автоматы|НКА]] эквивалентный [[Детерминированные конечные автоматы|ДКА]] следующим образом:&lt;br /&gt;
* Начало.&lt;br /&gt;
* '''Шаг 1''' Помещаем в очередь &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; множество, состоящее только из стартовой вершины.&lt;br /&gt;
* '''Шаг 2''' Затем, пока очередь не пуста выполняем следующие действия:&lt;br /&gt;
** Достаем из очереди множество, назовем его &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt;&lt;br /&gt;
** Для каждого &amp;lt;tex&amp;gt;c \in \Sigma&amp;lt;/tex&amp;gt; построим множество, содержащее состояния, в которые ведет символ &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; из каждого состояния из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt;. Затем положим построенное множество в очередь &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; только если оно не лежало там раньше. Каждое такое множество в итоговом ДКА будет отдельной вершиной, в которую будут вести переходы по соответствующим символам.&lt;br /&gt;
** Если в множестве &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; хотя бы одна из вершин была терминальной в НКА, то соответствующая данному множеству вершина в ДКА также будет терминальной.&lt;br /&gt;
* Конец&lt;br /&gt;
&lt;br /&gt;
== Построение эквивалентного ДКА по НКА ==&lt;br /&gt;
&lt;br /&gt;
Пусть нам дан произвольный НКА: &amp;lt;tex&amp;gt;\langle \Sigma , Q, s \in Q, T \subset Q, \delta : Q \times \Sigma \to 2^Q \rangle&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Построим по нему следующий ДКА: &amp;lt;tex&amp;gt;\langle \Sigma , Q_d, s_d \in Q_d, T_d \subset Q_d, \delta_d : Q_d \times \Sigma \to Q_d \rangle&amp;lt;/tex&amp;gt;, где:&lt;br /&gt;
# &amp;lt;tex&amp;gt;Q_d = \{q_d \mid q_d \subset 2^Q \}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;s_d = \{s\}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;T_d = \{q \in Q_d \mid \exists p \in T : p \in q\}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;\delta_d(q, c) = \{ \delta(a, c) \mid a \in q \}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Доказательство эквивалентности===&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
Построенный ДКА эквивалентен данному НКА.&lt;br /&gt;
|proof=&lt;br /&gt;
#Докажем, что любое слово, которое принимает НКА, будет принято построенным ДКА. Заметим, что &amp;lt;tex&amp;gt;\forall q \in q_d, \forall c \in \Sigma, \forall p \in \delta(q, c): p \in \delta_d(q_d, c)&amp;lt;/tex&amp;gt;. Рассмотрим слово &amp;lt;tex&amp;gt;w=w_1...w_m&amp;lt;/tex&amp;gt;, которое принимает автомат НКА: &amp;lt;tex&amp;gt;\langle s, w_1w_2 \dots w_m \rangle \vdash \langle u_1, w_2 \dots w_m \rangle \vdash \langle u_m, \varepsilon \rangle, u_m \in T&amp;lt;/tex&amp;gt;. Проверим, что построенный ДКА тоже принимает это слово. Заметим, что &amp;lt;tex&amp;gt;s \in s_d&amp;lt;/tex&amp;gt;, а, значит, исходя из нашего наблюдения, мы получаем, что &amp;lt;tex&amp;gt;u_1 \in {u_d}_1&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;{u_d}_1 = \delta_d(s, w_1)&amp;lt;/tex&amp;gt;. Далее, несложно заметить, что &amp;lt;tex&amp;gt;\forall i \leqslant m : u_i \in {u_d}_i&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\langle s_d, w_1w_2 \dots w_m \rangle \vdash \langle {u_d}_1, w_2 \dots w_m \rangle \vdash \langle {u_d}_i, w_{i + 1} \dots w_m\rangle&amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;tex&amp;gt;u_m \in {u_d}_m&amp;lt;/tex&amp;gt;, а из определения терминальных состояний в построенном ДКА мы получаем, что &amp;lt;tex&amp;gt;{u_d}_m \in T_d&amp;lt;/tex&amp;gt;, то есть наш ДКА тоже принимает cлово &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Докажем, что любое слово, которое принимает построенный ДКА, принимает и НКА. Сначала сделаем наблюдение, что если &amp;lt;tex&amp;gt;q_d=\{q\}&amp;lt;/tex&amp;gt;, и мы из него достигли по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; какого-то состояния &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\forall p \in p_d&amp;lt;/tex&amp;gt; существует путь из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; в НКА по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим слово &amp;lt;tex&amp;gt;w=w_1 \dots w_m&amp;lt;/tex&amp;gt;, которое принимает автомат ДКА: &amp;lt;tex&amp;gt;\langle s_d, w_1w_2 \dots w_m \rangle \vdash \langle {u_d}_1, w_2 \dots w_m \rangle \vdash \langle {u_d}_m, \varepsilon \rangle, {u_d}_m \in T_d&amp;lt;/tex&amp;gt;. Проверим, что НКА тоже принимает это слово. Так как &amp;lt;tex&amp;gt;s_d = \{s\}&amp;lt;/tex&amp;gt;, и мы из &amp;lt;tex&amp;gt;s_d&amp;lt;/tex&amp;gt; достигли &amp;lt;tex&amp;gt;{u_d}_m \in T_d&amp;lt;/tex&amp;gt;, возьмём любое терминальное состояние &amp;lt;tex&amp;gt;u_m \in {u_d}_m&amp;lt;/tex&amp;gt;. По нашему наблюдению в НКА есть путь из &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;u_m&amp;lt;/tex&amp;gt; по строке &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;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;
&amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; {{---}} очередь состояний, соответствующих множествам, состоящих из состояний НКА.&lt;br /&gt;
&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; {{---}} стартовое состояние НКА.&lt;br /&gt;
 '''Automaton''' getDFAbyNFA(&amp;lt;tex&amp;gt;\langle \Sigma, Q_0, s, T, \delta_0 \rangle&amp;lt;/tex&amp;gt; : '''Automaton'''):&lt;br /&gt;
   &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.push({s})&lt;br /&gt;
   '''while''' (&amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt; \neq &amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\varnothing &amp;lt;/tex&amp;gt;)&lt;br /&gt;
       &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.pop(&amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''for''' (&amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;\Sigma&amp;lt;/tex&amp;gt;)&lt;br /&gt;
           &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;\varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
           '''for''' (&amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt;) &lt;br /&gt;
              &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;p_d \cup \{ \delta_0(q, c) \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
           '''if''' ('''not''' visited[&amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;])&lt;br /&gt;
              &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;)&lt;br /&gt;
   '''return''' &amp;lt;tex&amp;gt;\langle \Sigma, Q, s, T, \delta \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Асимптотика===&lt;br /&gt;
Так как количество подмножеств множества состояний НКА не более, чем &amp;lt;tex&amp;gt;2^n&amp;lt;/tex&amp;gt;, а каждое подмножество мы обрабатываем ровно один раз за время &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;, получаем верхнюю оценку времени работы алгоритма {{---}} &amp;lt;tex&amp;gt;O(n \cdot 2^n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
Пусть нам дан [[Недетерминированные конечные автоматы|недетерминированный конечный автомат]]: &lt;br /&gt;
&lt;br /&gt;
[[Файл:DKA.png|250px]]&lt;br /&gt;
&lt;br /&gt;
По нашему заданию эквивалентного ДКА мы получаем: &lt;br /&gt;
&lt;br /&gt;
[[Файл:NKA_definition.png|250px]]&lt;br /&gt;
&lt;br /&gt;
#Помещаем в очередь множество из одной стартовой вершины — &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\{1\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Достаём из очереди множество &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1\}, a) = \{1, 2\}&amp;lt;/tex&amp;gt;, кладём множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь: &amp;lt;tex&amp;gt;Q = \{\{1, 2\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1\}, b) = \{1\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#Достаём из очереди множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1, 2\}, a) = \{1, 2\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1, 2\}, b) = \{1, 2\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#Помечаем все терминальные вершины, в данном случае — &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем ДКА, эквивалентный исходному: &lt;br /&gt;
&lt;br /&gt;
[[Файл:NKA_algorithm.png|250px]].&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;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE_%D0%9D%D0%9A%D0%90_%D1%8D%D0%BA%D0%B2%D0%B8%D0%B2%D0%B0%D0%BB%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%94%D0%9A%D0%90,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A2%D0%BE%D0%BC%D0%BF%D1%81%D0%BE%D0%BD%D0%B0&amp;diff=43443</id>
		<title>Построение по НКА эквивалентного ДКА, алгоритм Томпсона</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE_%D0%9D%D0%9A%D0%90_%D1%8D%D0%BA%D0%B2%D0%B8%D0%B2%D0%B0%D0%BB%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%94%D0%9A%D0%90,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A2%D0%BE%D0%BC%D0%BF%D1%81%D0%BE%D0%BD%D0%B0&amp;diff=43443"/>
				<updated>2015-01-05T06:17:32Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Описание ==&lt;br /&gt;
Алгоритм Томпсона строит по [[Недетерминированные конечные автоматы|НКА]] эквивалентный [[Детерминированные конечные автоматы|ДКА]] следующим образом:&lt;br /&gt;
* Начало.&lt;br /&gt;
* '''Шаг 1''' Помещаем в очередь &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; множество, состоящее только из стартовой вершины.&lt;br /&gt;
* '''Шаг 2''' Затем, пока очередь не пуста выполняем следующие действия:&lt;br /&gt;
** Достаем из очереди множество, назовем его &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt;&lt;br /&gt;
** Для каждого &amp;lt;tex&amp;gt;c \in \Sigma&amp;lt;/tex&amp;gt; построим множество, содержащее состояния, в которые ведет символ &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; из каждого состояния из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt;. Затем положим построенное множество в очередь &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; только если оно не лежало там раньше. Каждое такое множество в итоговом ДКА будет отдельной вершиной, в которую будут вести переходы по соответствующим символам.&lt;br /&gt;
** Если в множестве &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; хотя бы одна из вершин была терминальной в НКА, то соответствующая данному множеству вершина в ДКА также будет терминальной.&lt;br /&gt;
* Конец&lt;br /&gt;
&lt;br /&gt;
== Построение эквивалентного ДКА по НКА ==&lt;br /&gt;
&lt;br /&gt;
Пусть нам дан произвольный НКА: &amp;lt;tex&amp;gt;\langle \Sigma , Q, s \in Q, T \subset Q, \delta : Q \times \Sigma \to 2^Q \rangle&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Построим по нему следующий ДКА: &amp;lt;tex&amp;gt;\langle \Sigma , Q_d, s_d \in Q_d, T_d \subset Q_d, \delta_d : Q_d \times \Sigma \to Q_d \rangle&amp;lt;/tex&amp;gt;, где:&lt;br /&gt;
# &amp;lt;tex&amp;gt;Q_d = \{q_d \mid q_d \subset 2^Q \}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;s_d = \{s\}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;T_d = \{q \in Q_d \mid \exists p \in T : p \in q\}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;\delta_d(q, c) = \{ \delta(a, c) \mid a \in q \}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Доказательство эквивалентности===&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
Построенный ДКА эквивалентен данному НКА.&lt;br /&gt;
|proof=&lt;br /&gt;
#Докажем, что любое слово, которое принимает НКА, будет принято построенным ДКА. Заметим, что &amp;lt;tex&amp;gt;\forall q \in q_d, \forall c \in \Sigma, \forall p \in \delta(q, c): p \in \delta_d(q_d, c)&amp;lt;/tex&amp;gt;. Рассмотрим слово &amp;lt;tex&amp;gt;w=w_1...w_m&amp;lt;/tex&amp;gt;, которое принимает автомат НКА: &amp;lt;tex&amp;gt;\langle s, w_1w_2 \dots w_m \rangle \vdash \langle u_1, w_2 \dots w_m \rangle \vdash \langle u_m, \varepsilon \rangle, u_m \in T&amp;lt;/tex&amp;gt;. Проверим, что построенный ДКА тоже принимает это слово. Заметим, что &amp;lt;tex&amp;gt;s \in s_d&amp;lt;/tex&amp;gt;, а, значит, исходя из нашего наблюдения, мы получаем, что &amp;lt;tex&amp;gt;u_1 \in {u_d}_1&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;{u_d}_1 = \delta_d(s, w_1)&amp;lt;/tex&amp;gt;. Далее, несложно заметить, что &amp;lt;tex&amp;gt;\forall i \leqslant m : u_i \in {u_d}_i&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\langle s_d, w_1w_2 \dots w_m \rangle \vdash \langle {u_d}_1, w_2 \dots w_m \rangle \vdash \langle {u_d}_i, w_{i + 1} \dots w_m\rangle&amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;tex&amp;gt;u_m \in {u_d}_m&amp;lt;/tex&amp;gt;, а из определения терминальных состояний в построенном ДКА мы получаем, что &amp;lt;tex&amp;gt;{u_d}_m \in T_d&amp;lt;/tex&amp;gt;, то есть наш ДКА тоже принимает cлово &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Докажем, что любое слово, которое принимает построенный ДКА, принимает и НКА. Сначала сделаем наблюдение, что если &amp;lt;tex&amp;gt;q_d=\{q\}&amp;lt;/tex&amp;gt;, и мы из него достигли по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; какого-то состояния &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\forall p \in p_d&amp;lt;/tex&amp;gt; существует путь из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; в НКА по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим слово &amp;lt;tex&amp;gt;w=w_1 \dots w_m&amp;lt;/tex&amp;gt;, которое принимает автомат ДКА: &amp;lt;tex&amp;gt;\langle s_d, w_1w_2 \dots w_m \rangle \vdash \langle {u_d}_1, w_2 \dots w_m \rangle \vdash \langle {u_d}_m, \varepsilon \rangle, {u_d}_m \in T_d&amp;lt;/tex&amp;gt;. Проверим, что НКА тоже принимает это слово. Так как &amp;lt;tex&amp;gt;s_d = \{s\}&amp;lt;/tex&amp;gt;, и мы из &amp;lt;tex&amp;gt;s_d&amp;lt;/tex&amp;gt; достигли &amp;lt;tex&amp;gt;{u_d}_m \in T_d&amp;lt;/tex&amp;gt;, возьмём любое терминальное состояние &amp;lt;tex&amp;gt;u_m \in {u_d}_m&amp;lt;/tex&amp;gt;. По нашему наблюдению в НКА есть путь из &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;u_m&amp;lt;/tex&amp;gt; по строке &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;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;
&amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; {{---}} очередь состояний, соответствующих множествам, состоящих из состояний НКА.&lt;br /&gt;
&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; {{---}} стартовое состояние НКА.&lt;br /&gt;
 '''Automaton''' getDFAbyNFA(&amp;lt;tex&amp;gt;\langle \Sigma, Q_0, s, T, \delta_0 \rangle&amp;lt;/tex&amp;gt; : '''Automaton'''):&lt;br /&gt;
   &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.push({s})&lt;br /&gt;
   '''while''' (&amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt; \neq &amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\varnothing &amp;lt;/tex&amp;gt;)&lt;br /&gt;
       &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.pop(&amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''for''' (&amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;\Sigma&amp;lt;/tex&amp;gt;)&lt;br /&gt;
           &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;\varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
           '''for''' (&amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt;) &lt;br /&gt;
              &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;p_d \cup \{ \delta_0(q, c) \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
           '''if''' ('''not''' visited[&amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;])&lt;br /&gt;
              &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;)&lt;br /&gt;
   '''return''' &amp;lt;tex&amp;gt;\langle \Sigma, Q, s, T, \delta \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Асимптотика===&lt;br /&gt;
Так как количество подмножеств множества состояний НКА не более, чем &amp;lt;tex&amp;gt;2^n&amp;lt;/tex&amp;gt;, а каждое подмножество мы обрабатываем ровно один раз за время &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;, получаем верхнюю оценку времени работы алгоритма {{---}} &amp;lt;tex&amp;gt;O(n \cdot 2^n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
Пусть нам дан [[Недетерминированные конечные автоматы|недетерминированный конечный автомат]]: [[Файл:DKA.png|250px]]&lt;br /&gt;
&lt;br /&gt;
По нашему заданию эквивалентного ДКА мы получаем: [[Файл:NKA_definition.png|250px]]&lt;br /&gt;
&lt;br /&gt;
#Помещаем в очередь множество из одной стартовой вершины — &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\{1\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Достаём из очереди множество &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1\}, a) = \{1, 2\}&amp;lt;/tex&amp;gt;, кладём множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь: &amp;lt;tex&amp;gt;Q = \{\{1, 2\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1\}, b) = \{1\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#Достаём из очереди множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1, 2\}, a) = \{1, 2\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1, 2\}, b) = \{1, 2\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#Помечаем все терминальные вершины, в данном случае — &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем ДКА, эквивалентный исходному: [[Файл:NKA_algorithm.png|250px]].&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;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE_%D0%9D%D0%9A%D0%90_%D1%8D%D0%BA%D0%B2%D0%B8%D0%B2%D0%B0%D0%BB%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%94%D0%9A%D0%90,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A2%D0%BE%D0%BC%D0%BF%D1%81%D0%BE%D0%BD%D0%B0&amp;diff=43381</id>
		<title>Построение по НКА эквивалентного ДКА, алгоритм Томпсона</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE_%D0%9D%D0%9A%D0%90_%D1%8D%D0%BA%D0%B2%D0%B8%D0%B2%D0%B0%D0%BB%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%94%D0%9A%D0%90,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A2%D0%BE%D0%BC%D0%BF%D1%81%D0%BE%D0%BD%D0%B0&amp;diff=43381"/>
				<updated>2015-01-04T13:42:20Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: /* Алгоритм */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Описание ==&lt;br /&gt;
Алгоритм Томпсона строит по [[Недетерминированные конечные автоматы|НКА]] эквивалентный [[Детерминированные конечные автоматы|ДКА]] следующим образом:&lt;br /&gt;
* Помещаем в очередь &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; множество, состоящее только из стартовой вершины.&lt;br /&gt;
* Затем, пока очередь не пуста выполняем следующие действия:&lt;br /&gt;
** Достаем из очереди множество, назовем его &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt;&lt;br /&gt;
** Для каждого &amp;lt;tex&amp;gt;c \in \Sigma&amp;lt;/tex&amp;gt; построим множество, содержащее состояния, в которые ведет &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; по каждому состоянию из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt;. Затем положим построенное множество в очередь &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; только если оно не лежало там раньше. Каждое такое множество в итоговом ДКА будет отдельной вершиной, в которую будут вести переходы по соответствующим символам.&lt;br /&gt;
* Если в множестве &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; хотя бы одна из вершин была терминальной в НКА, то соответствующая данному множеству вершина в ДКА также будет терминальной.&lt;br /&gt;
&lt;br /&gt;
== Построение эквивалентного ДКА по НКА ==&lt;br /&gt;
&lt;br /&gt;
Пусть нам дан произвольный НКА: &amp;lt;tex&amp;gt;\langle \Sigma , Q, s \in Q, T \subset Q, \delta : Q \times \Sigma \to 2^Q \rangle&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Построим по нему следующий ДКА: &amp;lt;tex&amp;gt;\langle \Sigma , Q_d, s_d \in Q_d, T_d \subset Q_d, \delta_d : Q_d \times \Sigma \to Q_d \rangle&amp;lt;/tex&amp;gt;, где:&lt;br /&gt;
# &amp;lt;tex&amp;gt;Q_d = \{q_d \mid q_d \subset 2^Q \}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;s_d = \{s\}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;T_d = \{q \in Q_d \mid \exists p \in T : p \in q\}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;\delta_d(q, c) = \{ \delta(a, c) \mid a \in q \}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Доказательство эквивалентности===&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
Построенный ДКА эквивалентен данному НКА.&lt;br /&gt;
|proof=&lt;br /&gt;
#Докажем, что любое слово, которое принимает НКА, будет принято построенным ДКА. Заметим, что &amp;lt;tex&amp;gt;\forall q \in q_d, \forall c \in \Sigma, \forall p \in \delta(q, c): p \in \delta_d(q_d, c)&amp;lt;/tex&amp;gt;. Рассмотрим слово &amp;lt;tex&amp;gt;w=w_1...w_m&amp;lt;/tex&amp;gt;, которое принимает автомат НКА: &amp;lt;tex&amp;gt;\langle s, w_1w_2...w_m \rangle \vdash \langle u_1, w_2...w_m \rangle \vdash \langle u_m, \varepsilon \rangle, u_m \in T&amp;lt;/tex&amp;gt;. Проверим, что построенный ДКА тоже принимает это слово. Заметим, что &amp;lt;tex&amp;gt;s \in s_d&amp;lt;/tex&amp;gt;, а, значит, исходя из нашего наблюдения, мы получаем, что &amp;lt;tex&amp;gt;u_1 \in {u_d}_1&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;{u_d}_1 = \delta_d(s, w_1)&amp;lt;/tex&amp;gt;. Далее, несложно заметить, что &amp;lt;tex&amp;gt;\forall i \leqslant m : u_i \in {u_d}_i&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\langle s_d, w_1w_2...w_m \rangle \vdash \langle {u_d}_1, w_2...w_m \rangle \vdash \langle {u_d}_i, w_{i + 1}...w_m\rangle&amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;tex&amp;gt;u_m \in {u_d}_m&amp;lt;/tex&amp;gt;, а из определения терминальных состояний в построенном ДКА мы получаем, что &amp;lt;tex&amp;gt;{u_d}_m \in T_d&amp;lt;/tex&amp;gt;, то есть наш ДКА тоже принимает cлово &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Докажем, что любое слово, которое принимает построенный ДКА, принимает и НКА. Сначала сделаем наблюдение, что если &amp;lt;tex&amp;gt;q_d=\{q\}&amp;lt;/tex&amp;gt;, и мы из него достигли по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; какого-то состояния &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\forall p \in p_d&amp;lt;/tex&amp;gt; существует путь из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; в НКА по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим слово &amp;lt;tex&amp;gt;w=w_1...w_m&amp;lt;/tex&amp;gt;, которое принимает автомат ДКА: &amp;lt;tex&amp;gt;\langle s_d, w_1w_2...w_m \rangle \vdash \langle {u_d}_1, w_2...w_m \rangle \vdash \langle {u_d}_m, \varepsilon \rangle, {u_d}_m \in T_d&amp;lt;/tex&amp;gt;. Проверим, что НКА тоже принимает это слово. Так как &amp;lt;tex&amp;gt;s_d = \{s\}&amp;lt;/tex&amp;gt;, и мы из &amp;lt;tex&amp;gt;s_d&amp;lt;/tex&amp;gt; достигли &amp;lt;tex&amp;gt;{u_d}_m \in T_d&amp;lt;/tex&amp;gt;, возьмём любое терминальное состояние &amp;lt;tex&amp;gt;u_m \in {u_d}_m&amp;lt;/tex&amp;gt;. По нашему наблюдению в НКА есть путь из &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;u_m&amp;lt;/tex&amp;gt; по строке &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;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;
&amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; {{---}} очередь состояний, соответствующих множествам, состоящих из состояний НКА.&lt;br /&gt;
&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; {{---}} стартовое состояние НКА.&lt;br /&gt;
 '''Automaton''' getDFAbyNFA(&amp;lt;tex&amp;gt;\langle \Sigma, Q_0, s, T, \delta_0 \rangle&amp;lt;/tex&amp;gt; : '''Automaton'''):&lt;br /&gt;
   &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.push({s})&lt;br /&gt;
   '''while''' (&amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt; \neq &amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\varnothing &amp;lt;/tex&amp;gt;)&lt;br /&gt;
       &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.pop(&amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''for''' (&amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;\Sigma&amp;lt;/tex&amp;gt;)&lt;br /&gt;
           &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;\varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
           '''for''' (&amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt;) &lt;br /&gt;
              &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;p_d \cup \{ \delta_0(q, c) \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
           '''if''' ('''not''' visited[&amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;])&lt;br /&gt;
              &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;)&lt;br /&gt;
   '''return''' &amp;lt;tex&amp;gt;\langle \Sigma, Q, s, T, \delta \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Асимптотика===&lt;br /&gt;
Так как количество подмножеств множества состояний НКА не более, чем &amp;lt;tex&amp;gt;2^n&amp;lt;/tex&amp;gt;, а каждое подмножество мы обрабатываем ровно один раз за время &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;, получаем верхнюю оценку времени работы алгоритма {{---}} &amp;lt;tex&amp;gt;O(n \cdot 2^n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
Пусть нам дан [[Недетерминированные конечные автоматы|недетерминированный конечный автомат]]: [[Файл:DKA.png|250px]]&lt;br /&gt;
&lt;br /&gt;
По нашему заданию эквивалентного ДКА мы получаем: [[Файл:NKA_definition.png|250px]]&lt;br /&gt;
&lt;br /&gt;
#Помещаем в очередь множество из одной стартовой вершины — &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\{1\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Достаём из очереди множество &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1\}, a) = \{1, 2\}&amp;lt;/tex&amp;gt;, кладём множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь: &amp;lt;tex&amp;gt;Q = \{\{1, 2\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1\}, b) = \{1\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#Достаём из очереди множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1, 2\}, a) = \{1, 2\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1, 2\}, b) = \{1, 2\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#Помечаем все терминальные вершины, в данном случае — &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем ДКА, эквивалентный исходному: [[Файл:NKA_algorithm.png|250px]].&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;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE_%D0%9D%D0%9A%D0%90_%D1%8D%D0%BA%D0%B2%D0%B8%D0%B2%D0%B0%D0%BB%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%94%D0%9A%D0%90,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A2%D0%BE%D0%BC%D0%BF%D1%81%D0%BE%D0%BD%D0%B0&amp;diff=43380</id>
		<title>Построение по НКА эквивалентного ДКА, алгоритм Томпсона</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE_%D0%9D%D0%9A%D0%90_%D1%8D%D0%BA%D0%B2%D0%B8%D0%B2%D0%B0%D0%BB%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%94%D0%9A%D0%90,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A2%D0%BE%D0%BC%D0%BF%D1%81%D0%BE%D0%BD%D0%B0&amp;diff=43380"/>
				<updated>2015-01-04T13:41:38Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: /* Алгоритм */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Описание ==&lt;br /&gt;
Алгоритм Томпсона строит по [[Недетерминированные конечные автоматы|НКА]] эквивалентный [[Детерминированные конечные автоматы|ДКА]] следующим образом:&lt;br /&gt;
* Помещаем в очередь &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; множество, состоящее только из стартовой вершины.&lt;br /&gt;
* Затем, пока очередь не пуста выполняем следующие действия:&lt;br /&gt;
** Достаем из очереди множество, назовем его &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt;&lt;br /&gt;
** Для каждого &amp;lt;tex&amp;gt;c \in \Sigma&amp;lt;/tex&amp;gt; построим множество, содержащее состояния, в которые ведет &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; по каждому состоянию из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt;. Затем положим построенное множество в очередь &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; только если оно не лежало там раньше. Каждое такое множество в итоговом ДКА будет отдельной вершиной, в которую будут вести переходы по соответствующим символам.&lt;br /&gt;
* Если в множестве &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; хотя бы одна из вершин была терминальной в НКА, то соответствующая данному множеству вершина в ДКА также будет терминальной.&lt;br /&gt;
&lt;br /&gt;
== Построение эквивалентного ДКА по НКА ==&lt;br /&gt;
&lt;br /&gt;
Пусть нам дан произвольный НКА: &amp;lt;tex&amp;gt;\langle \Sigma , Q, s \in Q, T \subset Q, \delta : Q \times \Sigma \to 2^Q \rangle&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Построим по нему следующий ДКА: &amp;lt;tex&amp;gt;\langle \Sigma , Q_d, s_d \in Q_d, T_d \subset Q_d, \delta_d : Q_d \times \Sigma \to Q_d \rangle&amp;lt;/tex&amp;gt;, где:&lt;br /&gt;
# &amp;lt;tex&amp;gt;Q_d = \{q_d \mid q_d \subset 2^Q \}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;s_d = \{s\}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;T_d = \{q \in Q_d \mid \exists p \in T : p \in q\}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;\delta_d(q, c) = \{ \delta(a, c) \mid a \in q \}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Доказательство эквивалентности===&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
Построенный ДКА эквивалентен данному НКА.&lt;br /&gt;
|proof=&lt;br /&gt;
#Докажем, что любое слово, которое принимает НКА, будет принято построенным ДКА. Заметим, что &amp;lt;tex&amp;gt;\forall q \in q_d, \forall c \in \Sigma, \forall p \in \delta(q, c): p \in \delta_d(q_d, c)&amp;lt;/tex&amp;gt;. Рассмотрим слово &amp;lt;tex&amp;gt;w=w_1...w_m&amp;lt;/tex&amp;gt;, которое принимает автомат НКА: &amp;lt;tex&amp;gt;\langle s, w_1w_2...w_m \rangle \vdash \langle u_1, w_2...w_m \rangle \vdash \langle u_m, \varepsilon \rangle, u_m \in T&amp;lt;/tex&amp;gt;. Проверим, что построенный ДКА тоже принимает это слово. Заметим, что &amp;lt;tex&amp;gt;s \in s_d&amp;lt;/tex&amp;gt;, а, значит, исходя из нашего наблюдения, мы получаем, что &amp;lt;tex&amp;gt;u_1 \in {u_d}_1&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;{u_d}_1 = \delta_d(s, w_1)&amp;lt;/tex&amp;gt;. Далее, несложно заметить, что &amp;lt;tex&amp;gt;\forall i \leqslant m : u_i \in {u_d}_i&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\langle s_d, w_1w_2...w_m \rangle \vdash \langle {u_d}_1, w_2...w_m \rangle \vdash \langle {u_d}_i, w_{i + 1}...w_m\rangle&amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;tex&amp;gt;u_m \in {u_d}_m&amp;lt;/tex&amp;gt;, а из определения терминальных состояний в построенном ДКА мы получаем, что &amp;lt;tex&amp;gt;{u_d}_m \in T_d&amp;lt;/tex&amp;gt;, то есть наш ДКА тоже принимает cлово &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Докажем, что любое слово, которое принимает построенный ДКА, принимает и НКА. Сначала сделаем наблюдение, что если &amp;lt;tex&amp;gt;q_d=\{q\}&amp;lt;/tex&amp;gt;, и мы из него достигли по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; какого-то состояния &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\forall p \in p_d&amp;lt;/tex&amp;gt; существует путь из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; в НКА по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим слово &amp;lt;tex&amp;gt;w=w_1...w_m&amp;lt;/tex&amp;gt;, которое принимает автомат ДКА: &amp;lt;tex&amp;gt;\langle s_d, w_1w_2...w_m \rangle \vdash \langle {u_d}_1, w_2...w_m \rangle \vdash \langle {u_d}_m, \varepsilon \rangle, {u_d}_m \in T_d&amp;lt;/tex&amp;gt;. Проверим, что НКА тоже принимает это слово. Так как &amp;lt;tex&amp;gt;s_d = \{s\}&amp;lt;/tex&amp;gt;, и мы из &amp;lt;tex&amp;gt;s_d&amp;lt;/tex&amp;gt; достигли &amp;lt;tex&amp;gt;{u_d}_m \in T_d&amp;lt;/tex&amp;gt;, возьмём любое терминальное состояние &amp;lt;tex&amp;gt;u_m \in {u_d}_m&amp;lt;/tex&amp;gt;. По нашему наблюдению в НКА есть путь из &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;u_m&amp;lt;/tex&amp;gt; по строке &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;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;
&amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; {{---}} очередь состояний, соответствующих множествам, состоящих из состояний НКА.&lt;br /&gt;
&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; {{---}} стартовое состояние НКА.&lt;br /&gt;
 '''Automaton''' getDFAbyNFA(&amp;lt;tex&amp;gt;\langle \Sigma, Q_0, s, T, \delta \rangle&amp;lt;/tex&amp;gt; : '''Automaton'''):&lt;br /&gt;
   &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.push({s})&lt;br /&gt;
   '''while''' (&amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt; \neq &amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\varnothing &amp;lt;/tex&amp;gt;)&lt;br /&gt;
       &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.pop(&amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''for''' (&amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;\Sigma&amp;lt;/tex&amp;gt;)&lt;br /&gt;
           &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;\varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
           '''for''' (&amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt;) &lt;br /&gt;
              &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;p_d \cup \{ \delta(q, c) \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
           '''if''' ('''not''' visited[&amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;])&lt;br /&gt;
              &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;)&lt;br /&gt;
   '''return''' &amp;lt;tex&amp;gt;\langle \Sigma, Q, s, T, \delta \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Асимптотика===&lt;br /&gt;
Так как количество подмножеств множества состояний НКА не более, чем &amp;lt;tex&amp;gt;2^n&amp;lt;/tex&amp;gt;, а каждое подмножество мы обрабатываем ровно один раз за время &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;, получаем верхнюю оценку времени работы алгоритма {{---}} &amp;lt;tex&amp;gt;O(n \cdot 2^n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
Пусть нам дан [[Недетерминированные конечные автоматы|недетерминированный конечный автомат]]: [[Файл:DKA.png|250px]]&lt;br /&gt;
&lt;br /&gt;
По нашему заданию эквивалентного ДКА мы получаем: [[Файл:NKA_definition.png|250px]]&lt;br /&gt;
&lt;br /&gt;
#Помещаем в очередь множество из одной стартовой вершины — &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\{1\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Достаём из очереди множество &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1\}, a) = \{1, 2\}&amp;lt;/tex&amp;gt;, кладём множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь: &amp;lt;tex&amp;gt;Q = \{\{1, 2\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1\}, b) = \{1\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#Достаём из очереди множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1, 2\}, a) = \{1, 2\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1, 2\}, b) = \{1, 2\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#Помечаем все терминальные вершины, в данном случае — &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем ДКА, эквивалентный исходному: [[Файл:NKA_algorithm.png|250px]].&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;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE_%D0%9D%D0%9A%D0%90_%D1%8D%D0%BA%D0%B2%D0%B8%D0%B2%D0%B0%D0%BB%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%94%D0%9A%D0%90,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A2%D0%BE%D0%BC%D0%BF%D1%81%D0%BE%D0%BD%D0%B0&amp;diff=43376</id>
		<title>Построение по НКА эквивалентного ДКА, алгоритм Томпсона</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE_%D0%9D%D0%9A%D0%90_%D1%8D%D0%BA%D0%B2%D0%B8%D0%B2%D0%B0%D0%BB%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%94%D0%9A%D0%90,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A2%D0%BE%D0%BC%D0%BF%D1%81%D0%BE%D0%BD%D0%B0&amp;diff=43376"/>
				<updated>2015-01-04T13:31:50Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Описание ==&lt;br /&gt;
Алгоритм Томпсона строит по [[Недетерминированные конечные автоматы|НКА]] эквивалентный [[Детерминированные конечные автоматы|ДКА]] следующим образом:&lt;br /&gt;
* Помещаем в очередь &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; множество, состоящее только из стартовой вершины.&lt;br /&gt;
* Затем, пока очередь не пуста выполняем следующие действия:&lt;br /&gt;
** Достаем из очереди множество, назовем его &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt;&lt;br /&gt;
** Для каждого &amp;lt;tex&amp;gt;c \in \Sigma&amp;lt;/tex&amp;gt; построим множество, содержащее состояния, в которые ведет &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; по каждому состоянию из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt;. Затем положим построенное множество в очередь &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; только если оно не лежало там раньше. Каждое такое множество в итоговом ДКА будет отдельной вершиной, в которую будут вести переходы по соответствующим символам.&lt;br /&gt;
* Если в множестве &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; хотя бы одна из вершин была терминальной в НКА, то соответствующая данному множеству вершина в ДКА также будет терминальной.&lt;br /&gt;
&lt;br /&gt;
== Построение эквивалентного ДКА по НКА ==&lt;br /&gt;
&lt;br /&gt;
Пусть нам дан произвольный НКА: &amp;lt;tex&amp;gt;\langle \Sigma , Q, s \in Q, T \subset Q, \delta : Q \times \Sigma \to 2^Q \rangle&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Построим по нему следующий ДКА: &amp;lt;tex&amp;gt;\langle \Sigma , Q_d, s_d \in Q_d, T_d \subset Q_d, \delta_d : Q_d \times \Sigma \to Q_d \rangle&amp;lt;/tex&amp;gt;, где:&lt;br /&gt;
# &amp;lt;tex&amp;gt;Q_d = \{q_d \mid q_d \subset 2^Q \}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;s_d = \{s\}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;T_d = \{q \in Q_d \mid \exists p \in T : p \in q\}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;\delta_d(q, c) = \{ \delta(a, c) \mid a \in q \}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Доказательство эквивалентности===&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
Построенный ДКА эквивалентен данному НКА.&lt;br /&gt;
|proof=&lt;br /&gt;
#Докажем, что любое слово, которое принимает НКА, будет принято построенным ДКА. Заметим, что &amp;lt;tex&amp;gt;\forall q \in q_d, \forall c \in \Sigma, \forall p \in \delta(q, c): p \in \delta_d(q_d, c)&amp;lt;/tex&amp;gt;. Рассмотрим слово &amp;lt;tex&amp;gt;w=w_1...w_m&amp;lt;/tex&amp;gt;, которое принимает автомат НКА: &amp;lt;tex&amp;gt;\langle s, w_1w_2...w_m \rangle \vdash \langle u_1, w_2...w_m \rangle \vdash \langle u_m, \varepsilon \rangle, u_m \in T&amp;lt;/tex&amp;gt;. Проверим, что построенный ДКА тоже принимает это слово. Заметим, что &amp;lt;tex&amp;gt;s \in s_d&amp;lt;/tex&amp;gt;, а, значит, исходя из нашего наблюдения, мы получаем, что &amp;lt;tex&amp;gt;u_1 \in {u_d}_1&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;{u_d}_1 = \delta_d(s, w_1)&amp;lt;/tex&amp;gt;. Далее, несложно заметить, что &amp;lt;tex&amp;gt;\forall i \leqslant m : u_i \in {u_d}_i&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\langle s_d, w_1w_2...w_m \rangle \vdash \langle {u_d}_1, w_2...w_m \rangle \vdash \langle {u_d}_i, w_{i + 1}...w_m\rangle&amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;tex&amp;gt;u_m \in {u_d}_m&amp;lt;/tex&amp;gt;, а из определения терминальных состояний в построенном ДКА мы получаем, что &amp;lt;tex&amp;gt;{u_d}_m \in T_d&amp;lt;/tex&amp;gt;, то есть наш ДКА тоже принимает cлово &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Докажем, что любое слово, которое принимает построенный ДКА, принимает и НКА. Сначала сделаем наблюдение, что если &amp;lt;tex&amp;gt;q_d=\{q\}&amp;lt;/tex&amp;gt;, и мы из него достигли по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; какого-то состояния &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\forall p \in p_d&amp;lt;/tex&amp;gt; существует путь из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; в НКА по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим слово &amp;lt;tex&amp;gt;w=w_1...w_m&amp;lt;/tex&amp;gt;, которое принимает автомат ДКА: &amp;lt;tex&amp;gt;\langle s_d, w_1w_2...w_m \rangle \vdash \langle {u_d}_1, w_2...w_m \rangle \vdash \langle {u_d}_m, \varepsilon \rangle, {u_d}_m \in T_d&amp;lt;/tex&amp;gt;. Проверим, что НКА тоже принимает это слово. Так как &amp;lt;tex&amp;gt;s_d = \{s\}&amp;lt;/tex&amp;gt;, и мы из &amp;lt;tex&amp;gt;s_d&amp;lt;/tex&amp;gt; достигли &amp;lt;tex&amp;gt;{u_d}_m \in T_d&amp;lt;/tex&amp;gt;, возьмём любое терминальное состояние &amp;lt;tex&amp;gt;u_m \in {u_d}_m&amp;lt;/tex&amp;gt;. По нашему наблюдению в НКА есть путь из &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;u_m&amp;lt;/tex&amp;gt; по строке &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;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;
&amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; {{---}} очередь состояний, соответствующих множествам, состоящих из состояний НКА.&lt;br /&gt;
&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; {{---}} стартовое состояние НКА.&lt;br /&gt;
 '''Automaton''' getDFAbyNFA(NFA : '''Automaton'''):&lt;br /&gt;
   &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.push({s})&lt;br /&gt;
   '''while''' (&amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt; \neq &amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\varnothing &amp;lt;/tex&amp;gt;)&lt;br /&gt;
       &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.pop(&amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''for''' (&amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;\Sigma&amp;lt;/tex&amp;gt;)&lt;br /&gt;
           &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;\varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
           '''for''' (&amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt;) &lt;br /&gt;
              &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;p_d \cup \{ \delta(q, c) \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
           '''if''' ('''not''' visited[&amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;])&lt;br /&gt;
              &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;)&lt;br /&gt;
   '''return''' &amp;lt;tex&amp;gt;\langle \Sigma, Q, s, T, \delta \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Асимптотика===&lt;br /&gt;
Так как количество подмножеств множества состояний НКА не более, чем &amp;lt;tex&amp;gt;2^n&amp;lt;/tex&amp;gt;, а каждое подмножество мы обрабатываем ровно один раз за время &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;, получаем верхнюю оценку времени работы алгоритма {{---}} &amp;lt;tex&amp;gt;O(n \cdot 2^n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
Пусть нам дан [[Недетерминированные конечные автоматы|недетерминированный конечный автомат]]: [[Файл:DKA.png|250px]]&lt;br /&gt;
&lt;br /&gt;
По нашему заданию эквивалентного ДКА мы получаем: [[Файл:NKA_definition.png|250px]]&lt;br /&gt;
&lt;br /&gt;
#Помещаем в очередь множество из одной стартовой вершины — &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\{1\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Достаём из очереди множество &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1\}, a) = \{1, 2\}&amp;lt;/tex&amp;gt;, кладём множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь: &amp;lt;tex&amp;gt;Q = \{\{1, 2\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1\}, b) = \{1\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#Достаём из очереди множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1, 2\}, a) = \{1, 2\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1, 2\}, b) = \{1, 2\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#Помечаем все терминальные вершины, в данном случае — &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем ДКА, эквивалентный исходному: [[Файл:NKA_algorithm.png|250px]].&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;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE_%D0%9D%D0%9A%D0%90_%D1%8D%D0%BA%D0%B2%D0%B8%D0%B2%D0%B0%D0%BB%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%94%D0%9A%D0%90,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A2%D0%BE%D0%BC%D0%BF%D1%81%D0%BE%D0%BD%D0%B0&amp;diff=43374</id>
		<title>Построение по НКА эквивалентного ДКА, алгоритм Томпсона</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE_%D0%9D%D0%9A%D0%90_%D1%8D%D0%BA%D0%B2%D0%B8%D0%B2%D0%B0%D0%BB%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%94%D0%9A%D0%90,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A2%D0%BE%D0%BC%D0%BF%D1%81%D0%BE%D0%BD%D0%B0&amp;diff=43374"/>
				<updated>2015-01-04T12:41:02Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: /* Доказательство эквивалентности */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Построение эквивалентного ДКА по НКА ==&lt;br /&gt;
&lt;br /&gt;
Пусть нам дан произвольный [[Недетерминированные конечные автоматы|НКА]]: &amp;lt;tex&amp;gt;\langle \Sigma , Q, s \in Q, T \subset Q, \delta : Q \times \Sigma \to 2^Q \rangle&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Построим по нему следующий [[Детерминированные конечные автоматы|ДКА]]: &amp;lt;tex&amp;gt;\langle \Sigma , Q_d, s_d \in Q_d, T_d \subset Q_d, \delta_d : Q_d \times \Sigma \to Q_d \rangle&amp;lt;/tex&amp;gt;, где:&lt;br /&gt;
# &amp;lt;tex&amp;gt;Q_d = \{q_d \mid q_d \subset 2^Q \}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;s_d = \{s\}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;T_d = \{q \in Q_d \mid \exists p \in T : p \in q\}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;\delta_d(q, c) = \{ \delta(a, c) \mid a \in q \}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Доказательство эквивалентности===&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
Построенный ДКА эквивалентен данному НКА.&lt;br /&gt;
|proof=&lt;br /&gt;
#Докажем, что любое слово, которое принимает НКА, будет принято построенным ДКА. Заметим, что &amp;lt;tex&amp;gt;\forall q \in q_d, \forall c \in \Sigma, \forall p \in \delta(q, c): p \in \delta_d(q_d, c)&amp;lt;/tex&amp;gt;. Рассмотрим слово &amp;lt;tex&amp;gt;w=w_1...w_m&amp;lt;/tex&amp;gt;, которое принимает автомат НКА: &amp;lt;tex&amp;gt;\langle s, w_1w_2...w_m \rangle \vdash \langle u_1, w_2...w_m \rangle \vdash \langle u_m, \varepsilon \rangle, u_m \in T&amp;lt;/tex&amp;gt;. Проверим, что построенный ДКА тоже принимает это слово. Заметим, что &amp;lt;tex&amp;gt;s \in s_d&amp;lt;/tex&amp;gt;, а, значит, исходя из нашего наблюдения, мы получаем, что &amp;lt;tex&amp;gt;u_1 \in {u_d}_1&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;{u_d}_1 = \delta_d(s, w_1)&amp;lt;/tex&amp;gt;. Далее, несложно заметить, что &amp;lt;tex&amp;gt;\forall i \leqslant m : u_i \in {u_d}_i&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\langle s_d, w_1w_2...w_m \rangle \vdash \langle {u_d}_1, w_2...w_m \rangle \vdash \langle {u_d}_i, w_{i + 1}...w_m\rangle&amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;tex&amp;gt;u_m \in {u_d}_m&amp;lt;/tex&amp;gt;, а из определения терминальных состояний в построенном ДКА мы получаем, что &amp;lt;tex&amp;gt;{u_d}_m \in T_d&amp;lt;/tex&amp;gt;, то есть наш ДКА тоже принимает cлово &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Докажем, что любое слово, которое принимает построенный ДКА, принимает и НКА. Сначала сделаем наблюдение, что если &amp;lt;tex&amp;gt;q_d=\{q\}&amp;lt;/tex&amp;gt;, и мы из него достигли по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; какого-то состояния &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\forall p \in p_d&amp;lt;/tex&amp;gt; существует путь из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; в НКА по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим слово &amp;lt;tex&amp;gt;w=w_1...w_m&amp;lt;/tex&amp;gt;, которое принимает автомат ДКА: &amp;lt;tex&amp;gt;\langle s_d, w_1w_2...w_m \rangle \vdash \langle {u_d}_1, w_2...w_m \rangle \vdash \langle {u_d}_m, \varepsilon \rangle, {u_d}_m \in T_d&amp;lt;/tex&amp;gt;. Проверим, что НКА тоже принимает это слово. Так как &amp;lt;tex&amp;gt;s_d = \{s\}&amp;lt;/tex&amp;gt;, и мы из &amp;lt;tex&amp;gt;s_d&amp;lt;/tex&amp;gt; достигли &amp;lt;tex&amp;gt;{u_d}_m \in T_d&amp;lt;/tex&amp;gt;, возьмём любое терминальное состояние &amp;lt;tex&amp;gt;u_m \in {u_d}_m&amp;lt;/tex&amp;gt;. По нашему наблюдению в НКА есть путь из &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;u_m&amp;lt;/tex&amp;gt; по строке &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;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;
&amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; {{---}} очередь состояний, соответствующих множествам, состоящих из состояний НКА.&lt;br /&gt;
&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; {{---}} стартовое состояние НКА.&lt;br /&gt;
 '''Automaton''' getDFAbyNFA(NFA : '''Automaton'''):&lt;br /&gt;
   &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.push({s})&lt;br /&gt;
   '''while''' (&amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt; \neq &amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\varnothing &amp;lt;/tex&amp;gt;)&lt;br /&gt;
       &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.pop(&amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''for''' (&amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;\Sigma&amp;lt;/tex&amp;gt;)&lt;br /&gt;
           &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;\varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
           '''for''' (&amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt;) &lt;br /&gt;
              &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;p_d \cup \{ \delta(q, c) \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
           '''if''' ('''not''' visited[&amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;])&lt;br /&gt;
              &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;)&lt;br /&gt;
   '''return''' &amp;lt;tex&amp;gt;\langle \Sigma, Q, s, T, \delta \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Асимптотика===&lt;br /&gt;
Так как количество подмножеств множества состояний НКА не более, чем &amp;lt;tex&amp;gt;2^n&amp;lt;/tex&amp;gt;, а каждое подмножество мы обрабатываем ровно один раз за время &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;, получаем верхнюю оценку времени работы алгоритма {{---}} &amp;lt;tex&amp;gt;O(n \cdot 2^n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
Пусть нам дан [[Недетерминированные конечные автоматы|недетерминированный конечный автомат]]: [[Файл:DKA.png|250px]]&lt;br /&gt;
&lt;br /&gt;
По нашему заданию эквивалентного ДКА мы получаем: [[Файл:NKA_definition.png|250px]]&lt;br /&gt;
&lt;br /&gt;
#Помещаем в очередь множество из одной стартовой вершины — &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\{1\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Достаём из очереди множество &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1\}, a) = \{1, 2\}&amp;lt;/tex&amp;gt;, кладём множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь: &amp;lt;tex&amp;gt;Q = \{\{1, 2\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1\}, b) = \{1\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#Достаём из очереди множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1, 2\}, a) = \{1, 2\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1, 2\}, b) = \{1, 2\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#Помечаем все терминальные вершины, в данном случае — &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем ДКА, эквивалентный исходному: [[Файл:NKA_algorithm.png|250px]].&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;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE_%D0%9D%D0%9A%D0%90_%D1%8D%D0%BA%D0%B2%D0%B8%D0%B2%D0%B0%D0%BB%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%94%D0%9A%D0%90,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A2%D0%BE%D0%BC%D0%BF%D1%81%D0%BE%D0%BD%D0%B0&amp;diff=43372</id>
		<title>Построение по НКА эквивалентного ДКА, алгоритм Томпсона</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE_%D0%9D%D0%9A%D0%90_%D1%8D%D0%BA%D0%B2%D0%B8%D0%B2%D0%B0%D0%BB%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%94%D0%9A%D0%90,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A2%D0%BE%D0%BC%D0%BF%D1%81%D0%BE%D0%BD%D0%B0&amp;diff=43372"/>
				<updated>2015-01-04T12:38:25Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Построение эквивалентного ДКА по НКА ==&lt;br /&gt;
&lt;br /&gt;
Пусть нам дан произвольный [[Недетерминированные конечные автоматы|НКА]]: &amp;lt;tex&amp;gt;\langle \Sigma , Q, s \in Q, T \subset Q, \delta : Q \times \Sigma \to 2^Q \rangle&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Построим по нему следующий [[Детерминированные конечные автоматы|ДКА]]: &amp;lt;tex&amp;gt;\langle \Sigma , Q_d, s_d \in Q_d, T_d \subset Q_d, \delta_d : Q_d \times \Sigma \to Q_d \rangle&amp;lt;/tex&amp;gt;, где:&lt;br /&gt;
# &amp;lt;tex&amp;gt;Q_d = \{q_d \mid q_d \subset 2^Q \}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;s_d = \{s\}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;T_d = \{q \in Q_d \mid \exists p \in T : p \in q\}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;\delta_d(q, c) = \{ \delta(a, c) \mid a \in q \}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Доказательство эквивалентности===&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
Построенный ДКА эквивалентен данному НКА.&lt;br /&gt;
|proof=&lt;br /&gt;
#Докажем, что любое слово, которое принимает НКА, будет принято построенным ДКА. Заметим, что &amp;lt;tex&amp;gt;\forall q \in q_d, \forall c \in \Sigma, \forall p \in \delta(q, c): p \in \delta_d(q_d, c)&amp;lt;/tex&amp;gt;. Рассмотрим слово &amp;lt;tex&amp;gt;w=w_1...w_m&amp;lt;/tex&amp;gt;, которое принимает автомат НКА: &amp;lt;tex&amp;gt;\langle s, w_1w_2...w_m \rangle \vdash \langle u_1, w_2...w_m \rangle \vdash \langle u_m, \varepsilon \rangle, u_m \in T&amp;lt;/tex&amp;gt;. Проверим, что построенный ДКА тоже принимает это слово. Заметим, что &amp;lt;tex&amp;gt;s \in s_d&amp;lt;/tex&amp;gt;, а, значит, исходя из нашего наблюдения, мы получаем, что &amp;lt;tex&amp;gt;u_1 \in {u_d}_1&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;{u_d}_1 = \delta_d(s, w_1)&amp;lt;/tex&amp;gt;. Далее, несложно заметить, что &amp;lt;tex&amp;gt;\forall i \leq m : u_i \in {u_d}_i&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\langle s_d, w_1w_2...w_m \rangle \vdash \langle {u_d}_1, w_2...w_m \rangle \vdash \langle {u_d}_i, w_{i + 1}...w_m\rangle&amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;tex&amp;gt;u_m \in {u_d}_m&amp;lt;/tex&amp;gt;, а из определения терминальных состояний в построенном ДКА мы получаем, что &amp;lt;tex&amp;gt;{u_d}_m \in T_d&amp;lt;/tex&amp;gt;, то есть наш ДКА тоже принимает cлово &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Докажем, что любое слово, которое принимает построенный ДКА, принимает и НКА. Сначала сделаем наблюдение, что если &amp;lt;tex&amp;gt;q_d=\{q\}&amp;lt;/tex&amp;gt;, и мы из него достигли по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; какого-то состояния &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\forall p \in p_d&amp;lt;/tex&amp;gt; существует путь из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; в НКА по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим слово &amp;lt;tex&amp;gt;w=w_1...w_m&amp;lt;/tex&amp;gt;, которое принимает автомат ДКА: &amp;lt;tex&amp;gt;\langle s_d, w_1w_2...w_m \rangle \vdash \langle {u_d}_1, w_2...w_m \rangle \vdash \langle {u_d}_m, \varepsilon \rangle, {u_d}_m \in T_d&amp;lt;/tex&amp;gt;. Проверим, что НКА тоже принимает это слово. Так как &amp;lt;tex&amp;gt;s_d = \{s\}&amp;lt;/tex&amp;gt;, и мы из &amp;lt;tex&amp;gt;s_d&amp;lt;/tex&amp;gt; достигли &amp;lt;tex&amp;gt;{u_d}_m \in T_d&amp;lt;/tex&amp;gt;, возьмём любое терминальное состояние &amp;lt;tex&amp;gt;u_m \in {u_d}_m&amp;lt;/tex&amp;gt;. По нашему наблюдению в НКА есть путь из &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;u_m&amp;lt;/tex&amp;gt; по строке &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;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;
&amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; {{---}} очередь состояний, соответствующих множествам, состоящих из состояний НКА.&lt;br /&gt;
&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; {{---}} стартовое состояние НКА.&lt;br /&gt;
 '''Automaton''' getDFAbyNFA(NFA : '''Automaton'''):&lt;br /&gt;
   &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.push({s})&lt;br /&gt;
   '''while''' (&amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt; \neq &amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\varnothing &amp;lt;/tex&amp;gt;)&lt;br /&gt;
       &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.pop(&amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''for''' (&amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;\Sigma&amp;lt;/tex&amp;gt;)&lt;br /&gt;
           &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;\varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
           '''for''' (&amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt;) &lt;br /&gt;
              &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;p_d \cup \{ \delta(q, c) \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
           '''if''' ('''not''' visited[&amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;])&lt;br /&gt;
              &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;)&lt;br /&gt;
   '''return''' &amp;lt;tex&amp;gt;\langle \Sigma, Q, s, T, \delta \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Асимптотика===&lt;br /&gt;
Так как количество подмножеств множества состояний НКА не более, чем &amp;lt;tex&amp;gt;2^n&amp;lt;/tex&amp;gt;, а каждое подмножество мы обрабатываем ровно один раз за время &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;, получаем верхнюю оценку времени работы алгоритма {{---}} &amp;lt;tex&amp;gt;O(n \cdot 2^n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
Пусть нам дан [[Недетерминированные конечные автоматы|недетерминированный конечный автомат]]: [[Файл:DKA.png|250px]]&lt;br /&gt;
&lt;br /&gt;
По нашему заданию эквивалентного ДКА мы получаем: [[Файл:NKA_definition.png|250px]]&lt;br /&gt;
&lt;br /&gt;
#Помещаем в очередь множество из одной стартовой вершины — &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\{1\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Достаём из очереди множество &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1\}, a) = \{1, 2\}&amp;lt;/tex&amp;gt;, кладём множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь: &amp;lt;tex&amp;gt;Q = \{\{1, 2\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1\}, b) = \{1\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#Достаём из очереди множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1, 2\}, a) = \{1, 2\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1, 2\}, b) = \{1, 2\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#Помечаем все терминальные вершины, в данном случае — &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем ДКА, эквивалентный исходному: [[Файл:NKA_algorithm.png|250px]].&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;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE_%D0%9D%D0%9A%D0%90_%D1%8D%D0%BA%D0%B2%D0%B8%D0%B2%D0%B0%D0%BB%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%94%D0%9A%D0%90,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A2%D0%BE%D0%BC%D0%BF%D1%81%D0%BE%D0%BD%D0%B0&amp;diff=43370</id>
		<title>Построение по НКА эквивалентного ДКА, алгоритм Томпсона</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE_%D0%9D%D0%9A%D0%90_%D1%8D%D0%BA%D0%B2%D0%B8%D0%B2%D0%B0%D0%BB%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%94%D0%9A%D0%90,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A2%D0%BE%D0%BC%D0%BF%D1%81%D0%BE%D0%BD%D0%B0&amp;diff=43370"/>
				<updated>2015-01-04T12:35:32Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: /* Алгоритм */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Построение эквивалентного ДКА по НКА ==&lt;br /&gt;
&lt;br /&gt;
Пусть нам дан произвольный [[Недетерминированные конечные автоматы|НКА]]: &amp;lt;tex&amp;gt;\langle \Sigma , Q, s \in Q, T \subset Q, \delta : Q \times \Sigma \to 2^Q \rangle&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Построим по нему следующий [[Детерминированные конечные автоматы|ДКА]]: &amp;lt;tex&amp;gt;\langle \Sigma , Q_d, s_d \in Q_d, T_d \subset Q_d, \delta_d : Q_d \times \Sigma \to Q_d \rangle&amp;lt;/tex&amp;gt;, где:&lt;br /&gt;
# &amp;lt;tex&amp;gt;Q_d = \{q_d \mid q_d \subset 2^Q \}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;s_d = \{s\}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;T_d = \{q \in Q_d \mid \exists p \in T : p \in q\}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;\delta_d(q, c) = \{ \delta(a, c) \mid a \in q \}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Доказательство эквивалентности===&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
Построенный ДКА эквивалентен данному НКА.&lt;br /&gt;
|proof=&lt;br /&gt;
#Докажем, что любое слово, которое принимает НКА, будет принято построенным ДКА. Заметим, что &amp;lt;tex&amp;gt;\forall q \in q_d, \forall c \in \Sigma, \forall p \in \delta(q, c): p \in \delta_d(q_d, c)&amp;lt;/tex&amp;gt;. Рассмотрим слово &amp;lt;tex&amp;gt;w=w_1...w_m&amp;lt;/tex&amp;gt;, которое принимает автомат НКА: &amp;lt;tex&amp;gt;\langle s, w_1w_2...w_m \rangle \vdash \langle u_1, w_2...w_m \rangle \vdash \langle u_m, \varepsilon \rangle, u_m \in T&amp;lt;/tex&amp;gt;. Проверим, что построенный ДКА тоже принимает это слово. Заметим, что &amp;lt;tex&amp;gt;s \in s_d&amp;lt;/tex&amp;gt;, а, значит, исходя из нашего наблюдения, мы получаем, что &amp;lt;tex&amp;gt;u_1 \in {u_d}_1&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;{u_d}_1 = \delta_d(s, w_1)&amp;lt;/tex&amp;gt;. Далее, несложно заметить, что &amp;lt;tex&amp;gt;\forall i \leq m : u_i \in {u_d}_i&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\langle s_d, w_1w_2...w_m \rangle \vdash \langle {u_d}_1, w_2...w_m \rangle \vdash \langle {u_d}_i, w_{i + 1}...w_m\rangle&amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;tex&amp;gt;u_m \in {u_d}_m&amp;lt;/tex&amp;gt;, а из определения терминальных состояний в построенном ДКА мы получаем, что &amp;lt;tex&amp;gt;{u_d}_m \in T_d&amp;lt;/tex&amp;gt;, то есть наш ДКА тоже принимает cлово &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Докажем, что любое слово, которое принимает построенный ДКА, принимает и НКА. Сначала сделаем наблюдение, что если &amp;lt;tex&amp;gt;q_d=\{q\}&amp;lt;/tex&amp;gt;, и мы из него достигли по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; какого-то состояния &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\forall p \in p_d&amp;lt;/tex&amp;gt; существует путь из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; в НКА по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим слово &amp;lt;tex&amp;gt;w=w_1...w_m&amp;lt;/tex&amp;gt;, которое принимает автомат ДКА: &amp;lt;tex&amp;gt;\langle s_d, w_1w_2...w_m \rangle \vdash \langle {u_d}_1, w_2...w_m \rangle \vdash \langle {u_d}_m, \varepsilon \rangle, {u_d}_m \in T_d&amp;lt;/tex&amp;gt;. Проверим, что НКА тоже принимает это слово. Так как &amp;lt;tex&amp;gt;s_d = \{s\}&amp;lt;/tex&amp;gt;, и мы из &amp;lt;tex&amp;gt;s_d&amp;lt;/tex&amp;gt; достигли &amp;lt;tex&amp;gt;{u_d}_m \in T_d&amp;lt;/tex&amp;gt;, возьмём любое терминальное состояние &amp;lt;tex&amp;gt;u_m \in {u_d}_m&amp;lt;/tex&amp;gt;. По нашему наблюдению в НКА есть путь из &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;u_m&amp;lt;/tex&amp;gt; по строке &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;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;
&amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; {{---}} очередь состояний, соответствующих множествам, состоящих из состояний НКА.&lt;br /&gt;
&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; {{---}} стартовое состояние НКА.&lt;br /&gt;
 '''Automaton''' getDFAbyNFA(NFA : '''Automaton'''):&lt;br /&gt;
   &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.push({s})&lt;br /&gt;
   '''while''' (&amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt; \neq &amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\varnothing &amp;lt;/tex&amp;gt;)&lt;br /&gt;
       &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.pop(&amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''for''' (&amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;\Sigma&amp;lt;/tex&amp;gt;)&lt;br /&gt;
           &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;\varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
           '''for''' (&amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt;) &lt;br /&gt;
              &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;p_d \cup \{ \delta(q, c) \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
           '''if''' ('''not''' visited[&amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;])&lt;br /&gt;
              &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;)&lt;br /&gt;
   '''return''' &amp;lt;tex&amp;gt;\langle \Sigma, Q, s, T, \delta \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Асимптотика===&lt;br /&gt;
Так как количество подмножеств множества состояний НКА не более, чем &amp;lt;tex&amp;gt;2^n&amp;lt;/tex&amp;gt;, а каждое подмножество мы обрабатываем ровно один раз за время &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;, получаем верхнюю оценку времени работы алгоритма {{---}} &amp;lt;tex&amp;gt;O(n \cdot 2^n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
Пусть нам дан [[Недетерминированные конечные автоматы|недетерминированный конечный автомат]]: [[Файл:DKA.png|250px]]&lt;br /&gt;
&lt;br /&gt;
По нашему заданию эквивалентного ДКА мы получаем: [[Файл:NKA_definition.png|250px]]&lt;br /&gt;
&lt;br /&gt;
#Помещаем в очередь множество из одной стартовой вершины — &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\{1\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Достаём из очереди множество &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1\}, a) = \{1, 2\}&amp;lt;/tex&amp;gt;, кладём множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь: &amp;lt;tex&amp;gt;Q = \{\{1, 2\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1\}, b) = \{1\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#Достаём из очереди множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1, 2\}, a) = \{1, 2\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1, 2\}, b) = \{1, 2\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#Помечаем все терминальные вершины, в данном случае — &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем ДКА, эквивалентный исходному: [[Файл:NKA_algorithm.png|250px]].&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Автоматы и регулярные языки]]&lt;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE_%D0%9D%D0%9A%D0%90_%D1%8D%D0%BA%D0%B2%D0%B8%D0%B2%D0%B0%D0%BB%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%94%D0%9A%D0%90,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A2%D0%BE%D0%BC%D0%BF%D1%81%D0%BE%D0%BD%D0%B0&amp;diff=42601</id>
		<title>Построение по НКА эквивалентного ДКА, алгоритм Томпсона</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE_%D0%9D%D0%9A%D0%90_%D1%8D%D0%BA%D0%B2%D0%B8%D0%B2%D0%B0%D0%BB%D0%B5%D0%BD%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%94%D0%9A%D0%90,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A2%D0%BE%D0%BC%D0%BF%D1%81%D0%BE%D0%BD%D0%B0&amp;diff=42601"/>
				<updated>2014-12-20T19:20:16Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: /* Алгоритм */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Построение эквивалентного ДКА по НКА ==&lt;br /&gt;
&lt;br /&gt;
Пусть нам дан произвольный [[Недетерминированные конечные автоматы|НКА]]: &amp;lt;tex&amp;gt;\langle \Sigma , Q, s \in Q, T \subset Q, \delta : Q \times \Sigma \to 2^Q \rangle&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Построим по нему следующий [[Детерминированные конечные автоматы|ДКА]]: &amp;lt;tex&amp;gt;\langle \Sigma , Q_d, s_d \in Q_d, T_d \subset Q_d, \delta_d : Q_d \times \Sigma \to Q_d \rangle&amp;lt;/tex&amp;gt;, где:&lt;br /&gt;
# &amp;lt;tex&amp;gt;Q_d = \{q_d \mid q_d \subset 2^Q \}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;s_d = \{s\}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;T_d = \{q \in Q_d \mid \exists p \in T : p \in q\}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
# &amp;lt;tex&amp;gt;\delta_d(q, c) = \{ \delta(a, c) \mid a \in q \}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Доказательство эквивалентности===&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
Построенный ДКА эквивалентен данному НКА.&lt;br /&gt;
|proof=&lt;br /&gt;
#Докажем, что любое слово, которое принимает НКА, будет принято построенным ДКА. Заметим, что &amp;lt;tex&amp;gt;\forall q \in q_d, \forall c \in \Sigma, \forall p \in \delta(q, c): p \in \delta_d(q_d, c)&amp;lt;/tex&amp;gt;. Рассмотрим слово &amp;lt;tex&amp;gt;w=w_1...w_m&amp;lt;/tex&amp;gt;, которое принимает автомат НКА: &amp;lt;tex&amp;gt;\langle s, w_1w_2...w_m \rangle \vdash \langle u_1, w_2...w_m \rangle \vdash \langle u_m, \varepsilon \rangle, u_m \in T&amp;lt;/tex&amp;gt;. Проверим, что построенный ДКА тоже принимает это слово. Заметим, что &amp;lt;tex&amp;gt;s \in s_d&amp;lt;/tex&amp;gt;, а, значит, исходя из нашего наблюдения, мы получаем, что &amp;lt;tex&amp;gt;u_1 \in {u_d}_1&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;{u_d}_1 = \delta_d(s, w_1)&amp;lt;/tex&amp;gt;. Далее, несложно заметить, что &amp;lt;tex&amp;gt;\forall i \leq m : u_i \in {u_d}_i&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\langle s_d, w_1w_2...w_m \rangle \vdash \langle {u_d}_1, w_2...w_m \rangle \vdash \langle {u_d}_i, w_{i + 1}...w_m\rangle&amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;tex&amp;gt;u_m \in {u_d}_m&amp;lt;/tex&amp;gt;, а из определения терминальных состояний в построенном ДКА мы получаем, что &amp;lt;tex&amp;gt;{u_d}_m \in T_d&amp;lt;/tex&amp;gt;, то есть наш ДКА тоже принимает cлово &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Докажем, что любое слово, которое принимает построенный ДКА, принимает и НКА. Сначала сделаем наблюдение, что если &amp;lt;tex&amp;gt;q_d=\{q\}&amp;lt;/tex&amp;gt;, и мы из него достигли по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; какого-то состояния &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\forall p \in p_d&amp;lt;/tex&amp;gt; существует путь из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; в НКА по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим слово &amp;lt;tex&amp;gt;w=w_1...w_m&amp;lt;/tex&amp;gt;, которое принимает автомат ДКА: &amp;lt;tex&amp;gt;\langle s_d, w_1w_2...w_m \rangle \vdash \langle {u_d}_1, w_2...w_m \rangle \vdash \langle {u_d}_m, \varepsilon \rangle, {u_d}_m \in T_d&amp;lt;/tex&amp;gt;. Проверим, что НКА тоже принимает это слово. Так как &amp;lt;tex&amp;gt;s_d = \{s\}&amp;lt;/tex&amp;gt;, и мы из &amp;lt;tex&amp;gt;s_d&amp;lt;/tex&amp;gt; достигли &amp;lt;tex&amp;gt;{u_d}_m \in T_d&amp;lt;/tex&amp;gt;, возьмём любое терминальное состояние &amp;lt;tex&amp;gt;u_m \in {u_d}_m&amp;lt;/tex&amp;gt;. По нашему наблюдению в НКА есть путь из &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;u_m&amp;lt;/tex&amp;gt; по строке &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;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;
&amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; {{---}} очередь состояний, соответствующих множествам, состоящих из состояний НКА.&lt;br /&gt;
&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; {{---}} стартовое состояние НКА.&lt;br /&gt;
 '''Automaton''' getDKAbyNKA(&amp;lt;tex&amp;gt;\langle \Sigma, Q, s, T, \delta \rangle&amp;lt;/tex&amp;gt;: '''Automaton'''):&lt;br /&gt;
   &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.push({s})&lt;br /&gt;
   '''while''' (&amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt; \neq &amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\varnothing &amp;lt;/tex&amp;gt;)&lt;br /&gt;
       &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.pop(&amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt;)&lt;br /&gt;
       '''for''' (&amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;\Sigma&amp;lt;/tex&amp;gt;)&lt;br /&gt;
           &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;\varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
           '''for''' (&amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; '''in''' &amp;lt;tex&amp;gt;q_d&amp;lt;/tex&amp;gt;) &lt;br /&gt;
              &amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt; = &amp;lt;tex&amp;gt;p_d \cup \{ \delta(q, c) \}&amp;lt;/tex&amp;gt;&lt;br /&gt;
           '''if''' ('''not''' visited[&amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;])&lt;br /&gt;
              &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt;.push(&amp;lt;tex&amp;gt;p_d&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
===Асимптотика===&lt;br /&gt;
Так как количество подмножеств множества состояний НКА не более, чем &amp;lt;tex&amp;gt;2^n&amp;lt;/tex&amp;gt;, а каждое подмножество мы обрабатываем ровно один раз за время &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;, получаем верхнюю оценку времени работы алгоритма {{---}} &amp;lt;tex&amp;gt;O(n \cdot 2^n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
Пусть нам дан [[Недетерминированные конечные автоматы|недетерминированный конечный автомат]]: [[Файл:DKA.png|250px]]&lt;br /&gt;
&lt;br /&gt;
По нашему заданию эквивалентного ДКА мы получаем: [[Файл:NKA_definition.png|250px]]&lt;br /&gt;
&lt;br /&gt;
#Помещаем в очередь множество из одной стартовой вершины — &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\{1\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Достаём из очереди множество &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1\}, a) = \{1, 2\}&amp;lt;/tex&amp;gt;, кладём множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь: &amp;lt;tex&amp;gt;Q = \{\{1, 2\}\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1\}, b) = \{1\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#Достаём из очереди множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;Q = \{\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1, 2\}, a) = \{1, 2\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#&amp;lt;tex&amp;gt;q_d(\{1, 2\}, b) = \{1, 2\}&amp;lt;/tex&amp;gt;, нам не надо класть множество &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt; в очередь, так как оно уже там было.&lt;br /&gt;
#Помечаем все терминальные вершины, в данном случае — &amp;lt;tex&amp;gt;\{1, 2\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге получаем ДКА, эквивалентный исходному: [[Файл:NKA_algorithm.png|250px]].&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Автоматы и регулярные языки]]&lt;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9B%D0%B5%D0%BC%D0%BC%D0%B0_%D0%BE_%D0%B5%D0%B4%D0%B8%D0%BD%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D0%BE%D0%BC_%D0%BF%D0%B0%D1%80%D0%BE%D1%81%D0%BE%D1%87%D0%B5%D1%82%D0%B0%D0%BD%D0%B8%D0%B8_%D0%B2_%D0%B3%D1%80%D0%B0%D1%84%D0%B5_%D0%B7%D0%B0%D0%BC%D0%B5%D0%BD&amp;diff=37425</id>
		<title>Лемма о единственном паросочетании в графе замен</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9B%D0%B5%D0%BC%D0%BC%D0%B0_%D0%BE_%D0%B5%D0%B4%D0%B8%D0%BD%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D0%BE%D0%BC_%D0%BF%D0%B0%D1%80%D0%BE%D1%81%D0%BE%D1%87%D0%B5%D1%82%D0%B0%D0%BD%D0%B8%D0%B8_%D0%B2_%D0%B3%D1%80%D0%B0%D1%84%D0%B5_%D0%B7%D0%B0%D0%BC%D0%B5%D0%BD&amp;diff=37425"/>
				<updated>2014-05-30T20:04:42Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Утверждение&lt;br /&gt;
|statement=Пусть [[Двудольные_графы_и_раскраска_в_2_цвета|двудольный граф]] &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt; содержит единственное [[Связь_максимального_паросочетания_и_минимального_вершинного_покрытия_в_двудольных_графах#Связь_максимального_паросочетания_и_минимального_вершинного_покрытия_в_двудольном_графе|полное паросочетание]] &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt;. Тогда можно упорядочить вершины левой &amp;lt;tex&amp;gt;(a_i \in A)&amp;lt;/tex&amp;gt; и правой &amp;lt;tex&amp;gt;(b_i \in B)&amp;lt;/tex&amp;gt; долей таким образом, что &amp;lt;tex&amp;gt;\forall j &amp;gt; i : (a_i b_j) \notin G&amp;lt;/tex&amp;gt;. При этом рёбра паросочетания будут иметь вид &amp;lt;tex&amp;gt;(a_i b_i)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
|proof=Индукция по &amp;lt;tex&amp;gt;|A|&amp;lt;/tex&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
При &amp;lt;tex&amp;gt;|A|=1&amp;lt;/tex&amp;gt; утверждение очевидно. &amp;lt;br/&amp;gt;&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;|A|=n&amp;gt;1&amp;lt;/tex&amp;gt; (для &amp;lt;tex&amp;gt;|A|=n-1&amp;lt;/tex&amp;gt; утверждение верно). Возьмем произвольную вершину в левой доли. Будем строить из неё [[Теорема о максимальном паросочетании и дополняющих цепях#Паросочетание в двудольном графе|чередующуюся цепь]], добавляя по очереди ребро, входящее в &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt;, и ребро, не входящее в &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt;. Заметим, что такой путь не содержит циклов (циклы нечётной длины невозможны, так как граф двудольный, циклы чётной длины отсутствуют из-за единственности паросочетания). Если последнее добавленное ребро не принадлежит &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt;, то присоединим к цепи ребро из &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt;, инцидентное последней вершине. Значит, построение цепи прервется только при добавлении ребра из &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; при достижении вершины [[Основные определения теории графов#Степень вершины|степени]] &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
Таким образом, последнее ребро в цепи имеет вид &amp;lt;tex&amp;gt;(ab) \in M&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;a \in A, b \in B, \deg b = 1&amp;lt;/tex&amp;gt;. Положим &amp;lt;tex&amp;gt;a_n=a, b_n=b&amp;lt;/tex&amp;gt;. Для &amp;lt;tex&amp;gt;G \setminus \{a_n \cup b_n \}&amp;lt;/tex&amp;gt; утверждение верно по предположению индукции. С другой стороны, так как &amp;lt;tex&amp;gt;\deg b_n = 1&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;(a_i b_n) \notin G&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;n&amp;lt;/tex&amp;gt;, поэтому для &amp;lt;tex&amp;gt;j = n&amp;lt;/tex&amp;gt; утверждение также верно.&amp;lt;br/&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|about=&lt;br /&gt;
о единственном паросочетании в графе замен&lt;br /&gt;
|statement= Дан [[Определение матроида|матроид]] &amp;lt;tex&amp;gt;M = \langle X,I \rangle &amp;lt;/tex&amp;gt;. Пусть двудольный граф &amp;lt;tex&amp;gt;G_M(A) = \{ (x, y) | x \in A, y \notin A, A \setminus x \cup y \in I \}&amp;lt;/tex&amp;gt; содержит единственное полное паросочетание на &amp;lt;tex&amp;gt;A \triangle B&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;A\in I&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;|A| = |B|&amp;lt;/tex&amp;gt;. Тогда &amp;lt;tex&amp;gt;B \in I&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof= &lt;br /&gt;
[[Файл:Graph replacement.png|thumb|left|160px|]]&lt;br /&gt;
Упорядочим вершины левой &amp;lt;tex&amp;gt;(y_i \in A \setminus B)&amp;lt;/tex&amp;gt; и правой &amp;lt;tex&amp;gt;(z_j \in B \setminus A)&amp;lt;/tex&amp;gt; долей таким образом, что &amp;lt;tex&amp;gt;\forall j &amp;gt; i : (y_i z_j) \notin G_M(A)&amp;lt;/tex&amp;gt;. При таком упорядочивании ребра паросочетания имеют вид &amp;lt;tex&amp;gt;(y_i z_i)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Требуется доказать, что &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; независимо. Предположим обратное. Пусть &amp;lt;tex&amp;gt;B \notin I&amp;lt;/tex&amp;gt;, тогда существует [[Теорема о циклах|цикл]] &amp;lt;tex&amp;gt;C \subset B&amp;lt;/tex&amp;gt;.&amp;lt;br/&amp;gt; Выберем минимальное &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; такое, что &amp;lt;tex&amp;gt;z_i \in C&amp;lt;/tex&amp;gt;. Так как &amp;lt;tex&amp;gt;\forall j &amp;gt; i : (y_i z_j) \notin G_M(A)&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;A \setminus y_i \cup z_j \notin I&amp;lt;/tex&amp;gt;, следовательно, &amp;lt;tex&amp;gt;C \setminus z_i \subset \langle A \setminus y_i \rangle &amp;lt;/tex&amp;gt;. По [[Оператор замыкания для матроидов#theorem|свойствам замыкания 1 и 3]] получаем:&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt;C \setminus z_i \subset \langle A \setminus y_i \rangle \Rightarrow \langle C \setminus z_i \rangle \subset \langle \langle A \setminus y_i \rangle \rangle \Rightarrow \langle C \setminus z_i \rangle \subset \langle A \setminus y_i \rangle&amp;lt;/tex&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
Так как &amp;lt;tex&amp;gt;z_i \in \langle C \setminus z_i \rangle \subset \langle A \setminus y_i \rangle&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;A \setminus y_i \cup z_i \notin I&amp;lt;/tex&amp;gt;, то есть в &amp;lt;tex&amp;gt;G_M(A)&amp;lt;/tex&amp;gt; не существует ребра &amp;lt;tex&amp;gt;(y_i z_i)&amp;lt;/tex&amp;gt;. Но тогда, как было отмечено ранее, не существует полного паросочетания. Получили противоречие.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Источник ==&lt;br /&gt;
''Chandra Chekuri'' — [http://www.cs.illinois.edu/class/sp10/cs598csc/Lectures/Lecture16.pdf '''Combinatorial Optimization'''], с. 6&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория:Матроиды]]&lt;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9B%D0%B5%D0%BC%D0%BC%D0%B0_%D0%BE_%D0%B5%D0%B4%D0%B8%D0%BD%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D0%BE%D0%BC_%D0%BF%D0%B0%D1%80%D0%BE%D1%81%D0%BE%D1%87%D0%B5%D1%82%D0%B0%D0%BD%D0%B8%D0%B8_%D0%B2_%D0%B3%D1%80%D0%B0%D1%84%D0%B5_%D0%B7%D0%B0%D0%BC%D0%B5%D0%BD&amp;diff=37423</id>
		<title>Лемма о единственном паросочетании в графе замен</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9B%D0%B5%D0%BC%D0%BC%D0%B0_%D0%BE_%D0%B5%D0%B4%D0%B8%D0%BD%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D0%BE%D0%BC_%D0%BF%D0%B0%D1%80%D0%BE%D1%81%D0%BE%D1%87%D0%B5%D1%82%D0%B0%D0%BD%D0%B8%D0%B8_%D0%B2_%D0%B3%D1%80%D0%B0%D1%84%D0%B5_%D0%B7%D0%B0%D0%BC%D0%B5%D0%BD&amp;diff=37423"/>
				<updated>2014-05-30T20:03:10Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Утверждение&lt;br /&gt;
|statement=Пусть [[Двудольные_графы_и_раскраска_в_2_цвета|двудольный граф]] &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt; содержит единственное [[Связь_максимального_паросочетания_и_минимального_вершинного_покрытия_в_двудольных_графах#Связь_максимального_паросочетания_и_минимального_вершинного_покрытия_в_двудольном_графе|полное паросочетание]] &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt;. Тогда можно упорядочить вершины левой &amp;lt;tex&amp;gt;(a_i \in A)&amp;lt;/tex&amp;gt; и правой &amp;lt;tex&amp;gt;(b_i \in B)&amp;lt;/tex&amp;gt; долей таким образом, что &amp;lt;tex&amp;gt;\forall j &amp;gt; i : (a_i b_j) \notin G&amp;lt;/tex&amp;gt;. При этом рёбра паросочетания будут иметь вид &amp;lt;tex&amp;gt;(a_i b_i)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
|proof=Индукция по &amp;lt;tex&amp;gt;|A|&amp;lt;/tex&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
При &amp;lt;tex&amp;gt;|A|=1&amp;lt;/tex&amp;gt; утверждение очевидно. &amp;lt;br/&amp;gt;&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;|A|=n&amp;gt;1&amp;lt;/tex&amp;gt; (для &amp;lt;tex&amp;gt;|A|=n-1&amp;lt;/tex&amp;gt; утверждение верно). Возьмем произвольную вершину в левой доли. Будем строить из неё [[Теорема о максимальном паросочетании и дополняющих цепях#Паросочетание в двудольном графе|чередующуюся цепь]], добавляя по очереди ребро, входящее в &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt;, и ребро, не входящее в &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt;. Заметим, что такой путь не содержит циклов (циклы нечётной длины невозможны, так как граф двудольный, циклы чётной длины отсутствуют из-за единственности паросочетания). Если последнее добавленное ребро не принадлежит &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt;, то присоединим к цепи ребро из &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt;, инцидентное последней вершине. Значит, построение цепи прервется только при добавлении ребра из &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; при достижении вершины [[Основные определения теории графов#Степень вершины|степени]] 1. &amp;lt;br/&amp;gt;&lt;br /&gt;
Таким образом, последнее ребро в цепи имеет вид &amp;lt;tex&amp;gt;(ab) \in M&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;a \in A, b \in B, \deg b = 1&amp;lt;/tex&amp;gt;. Положим &amp;lt;tex&amp;gt;a_n=a, b_n=b&amp;lt;/tex&amp;gt;. Для &amp;lt;tex&amp;gt;G \setminus \{a_n \cup b_n \}&amp;lt;/tex&amp;gt; утверждение верно по предположению индукции. С другой стороны, так как &amp;lt;tex&amp;gt;\deg b_n = 1&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;(a_i b_n) \notin G&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;n&amp;lt;/tex&amp;gt;, поэтому для &amp;lt;tex&amp;gt;j = n&amp;lt;/tex&amp;gt; утверждение также верно.&amp;lt;br/&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|about=&lt;br /&gt;
о единственном паросочетании в графе замен&lt;br /&gt;
|statement= Дан [[Определение матроида|матроид]] &amp;lt;tex&amp;gt;M = \langle X,I \rangle &amp;lt;/tex&amp;gt;. Пусть двудольный граф &amp;lt;tex&amp;gt;G_M(A) = \{ (x, y) | x \in A, y \notin A, A \setminus x \cup y \in I \}&amp;lt;/tex&amp;gt; содержит единственное полное паросочетание на &amp;lt;tex&amp;gt;A \triangle B&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;A\in I&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;|A| = |B|&amp;lt;/tex&amp;gt;. Тогда &amp;lt;tex&amp;gt;B \in I&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof= &lt;br /&gt;
[[Файл:Graph replacement.png|thumb|left|160px|]]&lt;br /&gt;
Упорядочим вершины левой &amp;lt;tex&amp;gt;(y_i \in A \setminus B)&amp;lt;/tex&amp;gt; и правой &amp;lt;tex&amp;gt;(z_j \in B \setminus A)&amp;lt;/tex&amp;gt; долей таким образом, что &amp;lt;tex&amp;gt;\forall j &amp;gt; i : (y_i z_j) \notin G_M(A)&amp;lt;/tex&amp;gt;. При таком упорядочивании ребра паросочетания имеют вид &amp;lt;tex&amp;gt;(y_i z_i)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Требуется доказать, что &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; независимо. Предположим обратное. Пусть &amp;lt;tex&amp;gt;B \notin I&amp;lt;/tex&amp;gt;, тогда существует [[Теорема о циклах|цикл]] &amp;lt;tex&amp;gt;C \subset B&amp;lt;/tex&amp;gt;.&amp;lt;br/&amp;gt; Выберем минимальное &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; такое, что &amp;lt;tex&amp;gt;z_i \in C&amp;lt;/tex&amp;gt;. Так как &amp;lt;tex&amp;gt;\forall j &amp;gt; i : (y_i z_j) \notin G_M(A)&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;A \setminus y_i \cup z_j \notin I&amp;lt;/tex&amp;gt;, следовательно, &amp;lt;tex&amp;gt;C \setminus z_i \subset \langle A \setminus y_i \rangle &amp;lt;/tex&amp;gt;. По [[Оператор замыкания для матроидов#theorem|свойствам замыкания 1 и 3]] получаем:&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt;C \setminus z_i \subset \langle A \setminus y_i \rangle \Rightarrow \langle C \setminus z_i \rangle \subset \langle \langle A \setminus y_i \rangle \rangle \Rightarrow \langle C \setminus z_i \rangle \subset \langle A \setminus y_i \rangle&amp;lt;/tex&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
Так как &amp;lt;tex&amp;gt;z_i \in \langle C \setminus z_i \rangle \subset \langle A \setminus y_i \rangle&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;A \setminus y_i \cup z_i \notin I&amp;lt;/tex&amp;gt;, то есть в &amp;lt;tex&amp;gt;G_M(A)&amp;lt;/tex&amp;gt; не существует ребра &amp;lt;tex&amp;gt;(y_i z_i)&amp;lt;/tex&amp;gt;. Но тогда, как было отмечено ранее, не существует полного паросочетания. Получили противоречие.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Источник ==&lt;br /&gt;
''Chandra Chekuri'' — [http://www.cs.illinois.edu/class/sp10/cs598csc/Lectures/Lecture16.pdf '''Combinatorial Optimization'''], с. 6&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория:Матроиды]]&lt;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9B%D0%B5%D0%BC%D0%BC%D0%B0_%D0%BE_%D0%B5%D0%B4%D0%B8%D0%BD%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D0%BE%D0%BC_%D0%BF%D0%B0%D1%80%D0%BE%D1%81%D0%BE%D1%87%D0%B5%D1%82%D0%B0%D0%BD%D0%B8%D0%B8_%D0%B2_%D0%B3%D1%80%D0%B0%D1%84%D0%B5_%D0%B7%D0%B0%D0%BC%D0%B5%D0%BD&amp;diff=37420</id>
		<title>Лемма о единственном паросочетании в графе замен</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9B%D0%B5%D0%BC%D0%BC%D0%B0_%D0%BE_%D0%B5%D0%B4%D0%B8%D0%BD%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D0%BE%D0%BC_%D0%BF%D0%B0%D1%80%D0%BE%D1%81%D0%BE%D1%87%D0%B5%D1%82%D0%B0%D0%BD%D0%B8%D0%B8_%D0%B2_%D0%B3%D1%80%D0%B0%D1%84%D0%B5_%D0%B7%D0%B0%D0%BC%D0%B5%D0%BD&amp;diff=37420"/>
				<updated>2014-05-30T20:00:34Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Утверждение&lt;br /&gt;
|statement=Пусть [[Двудольные_графы_и_раскраска_в_2_цвета|двудольный граф]] &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt; содержит единственное [[Связь_максимального_паросочетания_и_минимального_вершинного_покрытия_в_двудольных_графах#Связь_максимального_паросочетания_и_минимального_вершинного_покрытия_в_двудольном_графе|полное паросочетание]] &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt;. Тогда можно упорядочить вершины левой &amp;lt;tex&amp;gt;(a_i \in A)&amp;lt;/tex&amp;gt; и правой &amp;lt;tex&amp;gt;(b_i \in B)&amp;lt;/tex&amp;gt; долей таким образом, что &amp;lt;tex&amp;gt;\forall j &amp;gt; i : (a_i b_j) \notin G&amp;lt;/tex&amp;gt;. При этом рёбра паросочетания будут иметь вид &amp;lt;tex&amp;gt;(a_i b_i)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
|proof=Индукция по &amp;lt;tex&amp;gt;|A|&amp;lt;/tex&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
При &amp;lt;tex&amp;gt;|A|=1&amp;lt;/tex&amp;gt; утверждение очевидно. &amp;lt;br/&amp;gt;&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;|A|=n&amp;gt;1&amp;lt;/tex&amp;gt; (для &amp;lt;tex&amp;gt;|A|=n-1&amp;lt;/tex&amp;gt; утверждение верно). Возьмем произвольную вершину в левой доли. Будем строить из неё [[Теорема о максимальном паросочетании и дополняющих цепях#Паросочетание в двудольном графе|чередующуюся цепь]], добавляя по очереди ребро, входящее в &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt;, и ребро, не входящее в &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt;. Заметим, что такой путь не содержит циклов (циклы нечётной длины невозможны, так как граф двудольный, циклы чётной длины отсутствуют из-за единственности паросочетания). Если последнее добавленное ребро не принадлежит &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt;, то присоединим к цепи ребро из &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt;, инцидентное последней вершине. Значит, построение цепи прервется только при добавлении ребра из &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; при достижении вершины [[Основные определения теории графов#Степень вершины|степени]] 1. &amp;lt;br/&amp;gt;&lt;br /&gt;
Таким образом, последнее ребро в цепи имеет вид &amp;lt;tex&amp;gt;(ab) \in M&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;a \in A, b \in B, \deg b = 1&amp;lt;/tex&amp;gt;. Положим &amp;lt;tex&amp;gt;a_n=a, b_n=b&amp;lt;/tex&amp;gt;. Для &amp;lt;tex&amp;gt;G \setminus \{a_n \cup b_n \}&amp;lt;/tex&amp;gt; утверждение верно по предположению индукции. С другой стороны, так как &amp;lt;tex&amp;gt;\deg b_n = 1&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;(a_i b_n) \notin G&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;n&amp;lt;/tex&amp;gt;, поэтому для &amp;lt;tex&amp;gt;j = n&amp;lt;/tex&amp;gt; утверждение также верно.&amp;lt;br/&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|about=&lt;br /&gt;
о единственном паросочетании в графе замен&lt;br /&gt;
|statement= Дан [[Определение матроида|матроид]] &amp;lt;tex&amp;gt;M = \langle X,I \rangle &amp;lt;/tex&amp;gt;. Пусть двудольный граф &amp;lt;tex&amp;gt;G_M(A) = \{ (x, y) | x \in A, y \notin A, A \setminus x \cup y \in I \}&amp;lt;/tex&amp;gt; содержит единственное полное паросочетание на &amp;lt;tex&amp;gt;A ^ B&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;A\in I&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;|A| = |B|&amp;lt;/tex&amp;gt;. Тогда &amp;lt;tex&amp;gt;B \in I&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof= &lt;br /&gt;
[[Файл:Graph replacement.png|thumb|left|160px|]]&lt;br /&gt;
Упорядочим вершины левой &amp;lt;tex&amp;gt;(y_i \in A \setminus B)&amp;lt;/tex&amp;gt; и правой &amp;lt;tex&amp;gt;(z_j \in B \setminus A)&amp;lt;/tex&amp;gt; долей таким образом, что &amp;lt;tex&amp;gt;\forall j &amp;gt; i : (y_i z_j) \notin G_M(A)&amp;lt;/tex&amp;gt;. При таком упорядочивании ребра паросочетания имеют вид &amp;lt;tex&amp;gt;(y_i z_i)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Требуется доказать, что &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; независимо. Предположим обратное. Пусть &amp;lt;tex&amp;gt;B \notin I&amp;lt;/tex&amp;gt;, тогда существует [[Теорема о циклах|цикл]] &amp;lt;tex&amp;gt;C \subset B&amp;lt;/tex&amp;gt;.&amp;lt;br/&amp;gt; Выберем минимальное &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; такое, что &amp;lt;tex&amp;gt;z_i \in C&amp;lt;/tex&amp;gt;. Так как &amp;lt;tex&amp;gt;\forall j &amp;gt; i : (y_i z_j) \notin G_M(A)&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;A \setminus y_i \cup z_j \notin I&amp;lt;/tex&amp;gt;, следовательно, &amp;lt;tex&amp;gt;C \setminus z_i \subset \langle A \setminus y_i \rangle &amp;lt;/tex&amp;gt;. По [[Оператор замыкания для матроидов#theorem|свойствам замыкания 1 и 3]] получаем:&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt;C \setminus z_i \subset \langle A \setminus y_i \rangle \Rightarrow \langle C \setminus z_i \rangle \subset \langle \langle A \setminus y_i \rangle \rangle \Rightarrow \langle C \setminus z_i \rangle \subset \langle A \setminus y_i \rangle&amp;lt;/tex&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
Так как &amp;lt;tex&amp;gt;z_i \in \langle C \setminus z_i \rangle \subset \langle A \setminus y_i \rangle&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;A \setminus y_i \cup z_i \notin I&amp;lt;/tex&amp;gt;, то есть в &amp;lt;tex&amp;gt;G_M(A)&amp;lt;/tex&amp;gt; не существует ребра &amp;lt;tex&amp;gt;(y_i z_i)&amp;lt;/tex&amp;gt;. Но тогда, как было отмечено ранее, не существует полного паросочетания. Получили противоречие.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Источник ==&lt;br /&gt;
''Chandra Chekuri'' — [http://www.cs.illinois.edu/class/sp10/cs598csc/Lectures/Lecture16.pdf '''Combinatorial Optimization'''], с. 6&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория:Матроиды]]&lt;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9B%D0%B5%D0%BC%D0%BC%D0%B0_%D0%BE_%D0%B5%D0%B4%D0%B8%D0%BD%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D0%BE%D0%BC_%D0%BF%D0%B0%D1%80%D0%BE%D1%81%D0%BE%D1%87%D0%B5%D1%82%D0%B0%D0%BD%D0%B8%D0%B8_%D0%B2_%D0%B3%D1%80%D0%B0%D1%84%D0%B5_%D0%B7%D0%B0%D0%BC%D0%B5%D0%BD&amp;diff=37418</id>
		<title>Лемма о единственном паросочетании в графе замен</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9B%D0%B5%D0%BC%D0%BC%D0%B0_%D0%BE_%D0%B5%D0%B4%D0%B8%D0%BD%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D0%BE%D0%BC_%D0%BF%D0%B0%D1%80%D0%BE%D1%81%D0%BE%D1%87%D0%B5%D1%82%D0%B0%D0%BD%D0%B8%D0%B8_%D0%B2_%D0%B3%D1%80%D0%B0%D1%84%D0%B5_%D0%B7%D0%B0%D0%BC%D0%B5%D0%BD&amp;diff=37418"/>
				<updated>2014-05-30T19:58:27Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: /* См. также */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Утверждение&lt;br /&gt;
|statement=Пусть [[Двудольные_графы_и_раскраска_в_2_цвета|двудольный граф]] &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt; содержит единственное [[Связь_максимального_паросочетания_и_минимального_вершинного_покрытия_в_двудольных_графах#Связь_максимального_паросочетания_и_минимального_вершинного_покрытия_в_двудольном_графе|полное паросочетание]] &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt;. Тогда можно упорядочить вершины левой &amp;lt;tex&amp;gt;(a_i \in A)&amp;lt;/tex&amp;gt; и правой &amp;lt;tex&amp;gt;(b_i \in B)&amp;lt;/tex&amp;gt; долей таким образом, что &amp;lt;tex&amp;gt;\forall j &amp;gt; i : (a_i b_j) \notin G&amp;lt;/tex&amp;gt;. При этом рёбра паросочетания будут иметь вид &amp;lt;tex&amp;gt;(a_i b_i)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
|proof=Индукция по &amp;lt;tex&amp;gt;|A|&amp;lt;/tex&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
При &amp;lt;tex&amp;gt;|A|=1&amp;lt;/tex&amp;gt; утверждение очевидно. &amp;lt;br/&amp;gt;&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;|A|=n&amp;gt;1&amp;lt;/tex&amp;gt; (для &amp;lt;tex&amp;gt;|A|=n-1&amp;lt;/tex&amp;gt; утверждение верно). Возьмем произвольную вершину в левой доли. Будем строить из неё [[Теорема о максимальном паросочетании и дополняющих цепях#Паросочетание в двудольном графе|чередующуюся цепь]], добавляя по очереди ребро, входящее в &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt;, и ребро, не входящее в &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt;. Заметим, что такой путь не содержит циклов (циклы нечётной длины невозможны, так как граф двудольный, циклы чётной длины отсутствуют из-за единственности паросочетания). Если последнее добавленное ребро не принадлежит &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt;, то присоединим к цепи ребро из &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt;, инцидентное последней вершине. Значит, построение цепи прервется только при добавлении ребра из &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; при достижении вершины [[Основные определения теории графов#Степень вершины|степени]] 1. &amp;lt;br/&amp;gt;&lt;br /&gt;
Таким образом, последнее ребро в цепи имеет вид &amp;lt;tex&amp;gt;(ab) \in M&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;a \in A, b \in B, \deg b = 1&amp;lt;/tex&amp;gt;. Положим &amp;lt;tex&amp;gt;a_n=a, b_n=b&amp;lt;/tex&amp;gt;. Для &amp;lt;tex&amp;gt;G \setminus \{a_n \cup b_n \}&amp;lt;/tex&amp;gt; утверждение верно по предположению индукции. С другой стороны, так как &amp;lt;tex&amp;gt;\deg b_n = 1&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;(a_i b_n) \notin G&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;n&amp;lt;/tex&amp;gt;, поэтому для &amp;lt;tex&amp;gt;j = n&amp;lt;/tex&amp;gt; утверждение также верно.&amp;lt;br/&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|about=&lt;br /&gt;
о единственном паросочетании в графе замен&lt;br /&gt;
|statement= Дан [[Определение матроида|матроид]] &amp;lt;tex&amp;gt;M = \langle X,I \rangle &amp;lt;/tex&amp;gt;. Пусть двудольный граф &amp;lt;tex&amp;gt;G_M(A) = \{ (x, y) | x \in A, y \notin A, A \setminus x \cup y \in I \}&amp;lt;/tex&amp;gt; содержит единственное полное паросочетание на &amp;lt;tex&amp;gt;A \oplus B&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;A\in I&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;|A| = |B|&amp;lt;/tex&amp;gt;. Тогда &amp;lt;tex&amp;gt;B \in I&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof= &lt;br /&gt;
[[Файл:Graph replacement.png|thumb|left|160px|]]&lt;br /&gt;
Упорядочим вершины левой &amp;lt;tex&amp;gt;(y_i \in A \setminus B)&amp;lt;/tex&amp;gt; и правой &amp;lt;tex&amp;gt;(z_j \in B \setminus A)&amp;lt;/tex&amp;gt; долей таким образом, что &amp;lt;tex&amp;gt;\forall j &amp;gt; i : (y_i z_j) \notin G_M(A)&amp;lt;/tex&amp;gt;. При таком упорядочивании ребра паросочетания имеют вид &amp;lt;tex&amp;gt;(y_i z_i)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Требуется доказать, что &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; независимо. Предположим обратное. Пусть &amp;lt;tex&amp;gt;B \notin I&amp;lt;/tex&amp;gt;, тогда существует [[Теорема о циклах|цикл]] &amp;lt;tex&amp;gt;C \subset B&amp;lt;/tex&amp;gt;.&amp;lt;br/&amp;gt; Выберем минимальное &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; такое, что &amp;lt;tex&amp;gt;z_i \in C&amp;lt;/tex&amp;gt;. Так как &amp;lt;tex&amp;gt;\forall j &amp;gt; i : (y_i z_j) \notin G_M(A)&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;A \setminus y_i \cup z_j \notin I&amp;lt;/tex&amp;gt;, следовательно, &amp;lt;tex&amp;gt;C \setminus z_i \subset \langle A \setminus y_i \rangle &amp;lt;/tex&amp;gt;. По [[Оператор замыкания для матроидов#theorem|свойствам замыкания 1 и 3]] получаем:&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt;C \setminus z_i \subset \langle A \setminus y_i \rangle \Rightarrow \langle C \setminus z_i \rangle \subset \langle \langle A \setminus y_i \rangle \rangle \Rightarrow \langle C \setminus z_i \rangle \subset \langle A \setminus y_i \rangle&amp;lt;/tex&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
Так как &amp;lt;tex&amp;gt;z_i \in \langle C \setminus z_i \rangle \subset \langle A \setminus y_i \rangle&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;A \setminus y_i \cup z_i \notin I&amp;lt;/tex&amp;gt;, то есть в &amp;lt;tex&amp;gt;G_M(A)&amp;lt;/tex&amp;gt; не существует ребра &amp;lt;tex&amp;gt;(y_i z_i)&amp;lt;/tex&amp;gt;. Но тогда, как было отмечено ранее, не существует полного паросочетания. Получили противоречие.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Источник ==&lt;br /&gt;
''Chandra Chekuri'' — [http://www.cs.illinois.edu/class/sp10/cs598csc/Lectures/Lecture16.pdf '''Combinatorial Optimization'''], с. 6&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория:Матроиды]]&lt;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9B%D0%B5%D0%BC%D0%BC%D0%B0_%D0%BE_%D0%B5%D0%B4%D0%B8%D0%BD%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D0%BE%D0%BC_%D0%BF%D0%B0%D1%80%D0%BE%D1%81%D0%BE%D1%87%D0%B5%D1%82%D0%B0%D0%BD%D0%B8%D0%B8_%D0%B2_%D0%B3%D1%80%D0%B0%D1%84%D0%B5_%D0%B7%D0%B0%D0%BC%D0%B5%D0%BD&amp;diff=37416</id>
		<title>Лемма о единственном паросочетании в графе замен</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9B%D0%B5%D0%BC%D0%BC%D0%B0_%D0%BE_%D0%B5%D0%B4%D0%B8%D0%BD%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D0%BE%D0%BC_%D0%BF%D0%B0%D1%80%D0%BE%D1%81%D0%BE%D1%87%D0%B5%D1%82%D0%B0%D0%BD%D0%B8%D0%B8_%D0%B2_%D0%B3%D1%80%D0%B0%D1%84%D0%B5_%D0%B7%D0%B0%D0%BC%D0%B5%D0%BD&amp;diff=37416"/>
				<updated>2014-05-30T19:55:17Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Утверждение&lt;br /&gt;
|statement=Пусть [[Двудольные_графы_и_раскраска_в_2_цвета|двудольный граф]] &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt; содержит единственное [[Связь_максимального_паросочетания_и_минимального_вершинного_покрытия_в_двудольных_графах#Связь_максимального_паросочетания_и_минимального_вершинного_покрытия_в_двудольном_графе|полное паросочетание]] &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt;. Тогда можно упорядочить вершины левой &amp;lt;tex&amp;gt;(a_i \in A)&amp;lt;/tex&amp;gt; и правой &amp;lt;tex&amp;gt;(b_i \in B)&amp;lt;/tex&amp;gt; долей таким образом, что &amp;lt;tex&amp;gt;\forall j &amp;gt; i : (a_i b_j) \notin G&amp;lt;/tex&amp;gt;. При этом рёбра паросочетания будут иметь вид &amp;lt;tex&amp;gt;(a_i b_i)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
|proof=Индукция по &amp;lt;tex&amp;gt;|A|&amp;lt;/tex&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
При &amp;lt;tex&amp;gt;|A|=1&amp;lt;/tex&amp;gt; утверждение очевидно. &amp;lt;br/&amp;gt;&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;|A|=n&amp;gt;1&amp;lt;/tex&amp;gt; (для &amp;lt;tex&amp;gt;|A|=n-1&amp;lt;/tex&amp;gt; утверждение верно). Возьмем произвольную вершину в левой доли. Будем строить из неё [[Теорема о максимальном паросочетании и дополняющих цепях#Паросочетание в двудольном графе|чередующуюся цепь]], добавляя по очереди ребро, входящее в &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt;, и ребро, не входящее в &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt;. Заметим, что такой путь не содержит циклов (циклы нечётной длины невозможны, так как граф двудольный, циклы чётной длины отсутствуют из-за единственности паросочетания). Если последнее добавленное ребро не принадлежит &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt;, то присоединим к цепи ребро из &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt;, инцидентное последней вершине. Значит, построение цепи прервется только при добавлении ребра из &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; при достижении вершины [[Основные определения теории графов#Степень вершины|степени]] 1. &amp;lt;br/&amp;gt;&lt;br /&gt;
Таким образом, последнее ребро в цепи имеет вид &amp;lt;tex&amp;gt;(ab) \in M&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;a \in A, b \in B, \deg b = 1&amp;lt;/tex&amp;gt;. Положим &amp;lt;tex&amp;gt;a_n=a, b_n=b&amp;lt;/tex&amp;gt;. Для &amp;lt;tex&amp;gt;G \setminus \{a_n \cup b_n \}&amp;lt;/tex&amp;gt; утверждение верно по предположению индукции. С другой стороны, так как &amp;lt;tex&amp;gt;\deg b_n = 1&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;(a_i b_n) \notin G&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;n&amp;lt;/tex&amp;gt;, поэтому для &amp;lt;tex&amp;gt;j = n&amp;lt;/tex&amp;gt; утверждение также верно.&amp;lt;br/&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|about=&lt;br /&gt;
о единственном паросочетании в графе замен&lt;br /&gt;
|statement= Дан [[Определение матроида|матроид]] &amp;lt;tex&amp;gt;M = \langle X,I \rangle &amp;lt;/tex&amp;gt;. Пусть двудольный граф &amp;lt;tex&amp;gt;G_M(A) = \{ (x, y) | x \in A, y \notin A, A \setminus x \cup y \in I \}&amp;lt;/tex&amp;gt; содержит единственное полное паросочетание на &amp;lt;tex&amp;gt;A \oplus B&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;A\in I&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;|A| = |B|&amp;lt;/tex&amp;gt;. Тогда &amp;lt;tex&amp;gt;B \in I&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof= &lt;br /&gt;
[[Файл:Graph replacement.png|thumb|left|160px|]]&lt;br /&gt;
Упорядочим вершины левой &amp;lt;tex&amp;gt;(y_i \in A \setminus B)&amp;lt;/tex&amp;gt; и правой &amp;lt;tex&amp;gt;(z_j \in B \setminus A)&amp;lt;/tex&amp;gt; долей таким образом, что &amp;lt;tex&amp;gt;\forall j &amp;gt; i : (y_i z_j) \notin G_M(A)&amp;lt;/tex&amp;gt;. При таком упорядочивании ребра паросочетания имеют вид &amp;lt;tex&amp;gt;(y_i z_i)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Требуется доказать, что &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; независимо. Предположим обратное. Пусть &amp;lt;tex&amp;gt;B \notin I&amp;lt;/tex&amp;gt;, тогда существует [[Теорема о циклах|цикл]] &amp;lt;tex&amp;gt;C \subset B&amp;lt;/tex&amp;gt;.&amp;lt;br/&amp;gt; Выберем минимальное &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; такое, что &amp;lt;tex&amp;gt;z_i \in C&amp;lt;/tex&amp;gt;. Так как &amp;lt;tex&amp;gt;\forall j &amp;gt; i : (y_i z_j) \notin G_M(A)&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;A \setminus y_i \cup z_j \notin I&amp;lt;/tex&amp;gt;, следовательно, &amp;lt;tex&amp;gt;C \setminus z_i \subset \langle A \setminus y_i \rangle &amp;lt;/tex&amp;gt;. По [[Оператор замыкания для матроидов#theorem|свойствам замыкания 1 и 3]] получаем:&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt;C \setminus z_i \subset \langle A \setminus y_i \rangle \Rightarrow \langle C \setminus z_i \rangle \subset \langle \langle A \setminus y_i \rangle \rangle \Rightarrow \langle C \setminus z_i \rangle \subset \langle A \setminus y_i \rangle&amp;lt;/tex&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
Так как &amp;lt;tex&amp;gt;z_i \in \langle C \setminus z_i \rangle \subset \langle A \setminus y_i \rangle&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;A \setminus y_i \cup z_i \notin I&amp;lt;/tex&amp;gt;, то есть в &amp;lt;tex&amp;gt;G_M(A)&amp;lt;/tex&amp;gt; не существует ребра &amp;lt;tex&amp;gt;(y_i z_i)&amp;lt;/tex&amp;gt;. Но тогда, как было отмечено ранее, не существует полного паросочетания. Получили противоречие.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
*[[Алгоритм_Дейкстры|Алгоритм Дейкстры]]&lt;br /&gt;
== Источник ==&lt;br /&gt;
''Chandra Chekuri'' — [http://www.cs.illinois.edu/class/sp10/cs598csc/Lectures/Lecture16.pdf '''Combinatorial Optimization'''], с. 6&lt;br /&gt;
&lt;br /&gt;
[[Категория:Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория:Матроиды]]&lt;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%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=37408</id>
		<title>Алгоритм Кнута-Морриса-Пратта</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%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=37408"/>
				<updated>2014-05-30T19:36:08Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Алгоритм Кнута — Морриса — Пратта''' (англ. ''Knuth–Morris–Pratt algorithm'') — алгоритм [[Наивный алгоритм поиска подстроки в строке#Постановка задачи|поиска подстроки в строке]].&lt;br /&gt;
&lt;br /&gt;
==Описание алгоритма==&lt;br /&gt;
Дана цепочка &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; и образец &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;. Требуется найти все позиции, начиная с которых &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; входит в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Построим строку &amp;lt;tex&amp;gt;S = P\#T&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;gt; — любой символ, не входящий в алфавит &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;. Посчитаем на ней значение [[Префикс-функция|префикс-функции]]. Благодаря разделительному символу &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;gt;, выполняется &amp;lt;tex&amp;gt;\forall i: \pi[i] \leqslant |P|&amp;lt;/tex&amp;gt;. Заметим, что по определению [[Префикс-функция|префикс-функции]] при &amp;lt;tex&amp;gt;i &amp;gt; |P|&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\pi[i] = |P|&amp;lt;/tex&amp;gt; подстроки длины &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;, начинающиеся с позиций &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;i - |P| + 1&amp;lt;/tex&amp;gt;, совпадают. Соберем все такие позиции &amp;lt;tex&amp;gt;i - |P| + 1&amp;lt;/tex&amp;gt; строки &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, вычтем из каждой позиции &amp;lt;tex&amp;gt;|P| + 1&amp;lt;/tex&amp;gt;, это и будет ответ. Другими словами, если в какой-то позиции &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; выполняется условие &amp;lt;tex&amp;gt;\pi[i]=|P|&amp;lt;/tex&amp;gt;, то в этой позиции начинается очередное вхождение образца в цепочку.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:kmp_pict2.png|640px]]&lt;br /&gt;
&lt;br /&gt;
==Псевдокод==&lt;br /&gt;
 '''int'''[] kmp('''string''' T, '''string''' P)&lt;br /&gt;
    '''int''' p = P.length&lt;br /&gt;
    '''int''' t = T.length&lt;br /&gt;
    '''int'''[] answer&lt;br /&gt;
    '''int'''[] &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt; = [[Префикс-функция#Эффективный_алгоритм|prefixFunction(P + &amp;quot;#&amp;quot; + T)]]&lt;br /&gt;
    '''int''' count = 0&lt;br /&gt;
    '''for''' i = 0 .. t - 1&lt;br /&gt;
       '''if''' &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;[p + i + 1] == p&lt;br /&gt;
          answer[count++] = i&lt;br /&gt;
    '''return''' answer&lt;br /&gt;
&lt;br /&gt;
==Время работы==&lt;br /&gt;
Префикс-функция от строки &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; строится за &amp;lt;tex&amp;gt;O(S) = O(P + T)&amp;lt;/tex&amp;gt;. Проход цикла по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; содержит &amp;lt;tex&amp;gt;O(T)&amp;lt;/tex&amp;gt; итераций. Итого, время работы алгоритма оценивается как &amp;lt;tex&amp;gt;O(P + T)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Оценка по памяти==&lt;br /&gt;
Предложенная реализация имеет оценку по памяти &amp;lt;tex&amp;gt;O(P+T)&amp;lt;/tex&amp;gt;. Оценки &amp;lt;tex&amp;gt;O(P)&amp;lt;/tex&amp;gt; можно добиться за счет отказа от запоминания значений префикс-функции для позиций в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, меньших &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; (т.е. до начала цепочки &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;). Это возможно, так как значение префикс функции не может превысить длину образца, благодаря разделительному символу &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;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:ru:Алгоритм Кнута — Морриса — Пратта | Википедия {{---}} Алгоритм Кнута — Морриса — Пратта]]&lt;br /&gt;
*[[wikipedia:en:Knuth–Morris–Pratt algorithm | Wikipedia {{---}} Knuth–Morris–Pratt algorithm]]&lt;br /&gt;
*Кормен, Т., Лейзерсон, Ч., Ривест, Р., Штайн — Алгоритмы: построение и анализ / пер. с англ. — изд. 2-е — М.: Издательский дом «Вильямс», 2009. — с.1036. — ISBN 978-5-8459-0857-5.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Поиск подстроки в строке]]&lt;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%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=37406</id>
		<title>Алгоритм Кнута-Морриса-Пратта</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%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=37406"/>
				<updated>2014-05-30T19:31:48Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Алгоритм Кнута — Морриса — Пратта''' (англ. ''Knuth–Morris–Pratt algorithm'') — алгоритм [[Наивный алгоритм поиска подстроки в строке#Постановка задачи|поиска подстроки в строке]].&lt;br /&gt;
&lt;br /&gt;
==Описание алгоритма==&lt;br /&gt;
Дана цепочка &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; и образец &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;. Требуется найти все позиции, начиная с которых &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; входит в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Построим строку &amp;lt;tex&amp;gt;S = P\#T&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;gt; — любой символ, не входящий в алфавит &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;. Посчитаем на ней значение [[Префикс-функция|префикс-функции]]. Благодаря разделительному символу &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;gt;, выполняется &amp;lt;tex&amp;gt;\forall i: \pi(i) \leqslant |P|&amp;lt;/tex&amp;gt;. Заметим, что по определению [[Префикс-функция|префикс-функции]] при &amp;lt;tex&amp;gt;i &amp;gt; |P|&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\pi(i) = |P|&amp;lt;/tex&amp;gt; подстроки длины &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;, начинающиеся с позиций &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;i - |P| + 1&amp;lt;/tex&amp;gt;, совпадают. Соберем все такие позиции &amp;lt;tex&amp;gt;i - |P| + 1&amp;lt;/tex&amp;gt; строки &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, вычтем из каждой позиции &amp;lt;tex&amp;gt;|P| + 1&amp;lt;/tex&amp;gt;, это и будет ответ. Другими словами, если в какой-то позиции &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; выполняется условие &amp;lt;tex&amp;gt;\pi(i)=|P|&amp;lt;/tex&amp;gt;, то в этой позиции начинается очередное вхождение образца в цепочку.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:kmp_pict2.png|640px]]&lt;br /&gt;
&lt;br /&gt;
==Псевдокод==&lt;br /&gt;
 '''int'''[] kmp('''string''' T, '''string''' P)&lt;br /&gt;
    '''int''' p = P.length&lt;br /&gt;
    '''int''' t = T.length&lt;br /&gt;
    '''int'''[] answer&lt;br /&gt;
    '''int'''[] &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt; = [[Префикс-функция#Эффективный_алгоритм|prefixFunction(P + &amp;quot;#&amp;quot; + T)]]&lt;br /&gt;
    '''int''' count = 0&lt;br /&gt;
    '''for''' i = 0 .. (t - 1)&lt;br /&gt;
       '''if''' &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;[p + i + 1] == p&lt;br /&gt;
          answer[count++] = i&lt;br /&gt;
    '''return''' answer&lt;br /&gt;
&lt;br /&gt;
==Время работы==&lt;br /&gt;
Префикс-функция от строки &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; строится за &amp;lt;tex&amp;gt;O(S) = O(P + T)&amp;lt;/tex&amp;gt;. Проход цикла по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; содержит &amp;lt;tex&amp;gt;O(T)&amp;lt;/tex&amp;gt; итераций. Итого, время работы алгоритма оценивается как &amp;lt;tex&amp;gt;O(P + T)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Оценка по памяти==&lt;br /&gt;
Предложенная реализация имеет оценку по памяти &amp;lt;tex&amp;gt;O(P+T)&amp;lt;/tex&amp;gt;. Оценки &amp;lt;tex&amp;gt;O(P)&amp;lt;/tex&amp;gt; можно добиться за счет отказа от запоминания значений префикс-функции для позиций в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, меньших &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; (т.е. до начала цепочки &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;). Это возможно, так как значение префикс функции не может превысить длину образца, благодаря разделительному символу &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;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:ru:Алгоритм Кнута — Морриса — Пратта | Википедия {{---}} Алгоритм Кнута — Морриса — Пратта]]&lt;br /&gt;
*[[wikipedia:en:Knuth–Morris–Pratt algorithm | Wikipedia {{---}} Knuth–Morris–Pratt algorithm]]&lt;br /&gt;
*Кормен, Т., Лейзерсон, Ч., Ривест, Р., Штайн — Алгоритмы: построение и анализ / пер. с англ. — изд. 2-е — М.: Издательский дом «Вильямс», 2009. — с.1036. — ISBN 978-5-8459-0857-5.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Поиск подстроки в строке]]&lt;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%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=37404</id>
		<title>Алгоритм Кнута-Морриса-Пратта</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%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=37404"/>
				<updated>2014-05-30T19:30:21Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Алгоритм Кнута — Морриса — Пратта''' (англ. ''Knuth–Morris–Pratt algorithm'') — алгоритм [[Наивный алгоритм поиска подстроки в строке#Постановка задачи|поиска подстроки в строке]].&lt;br /&gt;
&lt;br /&gt;
==Описание алгоритма==&lt;br /&gt;
Дана цепочка &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; и образец &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;. Требуется найти все позиции, начиная с которых &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; входит в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Построим строку &amp;lt;tex&amp;gt;S = P\#T&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;gt; — любой символ, не входящий в алфавит &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;. Посчитаем на ней значение [[Префикс-функция|префикс-функции]]. Благодаря разделительному символу &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;gt;, выполняется &amp;lt;tex&amp;gt;\forall i: \pi(i) \leqslant |P|&amp;lt;/tex&amp;gt;. Заметим, что по определению [[Префикс-функция|префикс-функции]] при &amp;lt;tex&amp;gt;i &amp;gt; |P|&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\pi(i) = |P|&amp;lt;/tex&amp;gt; подстроки длины &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;, начинающиеся с позиций &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;i - |P| + 1&amp;lt;/tex&amp;gt;, совпадают. Соберем все такие позиции &amp;lt;tex&amp;gt;i - |P| + 1&amp;lt;/tex&amp;gt; строки &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, вычтем из каждой позиции &amp;lt;tex&amp;gt;|P| + 1&amp;lt;/tex&amp;gt;, это и будет ответ. Другими словами, если в какой-то позиции &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; выполняется условие &amp;lt;tex&amp;gt;\pi(i)=|P|&amp;lt;/tex&amp;gt;, то в этой позиции начинается очередное вхождение образца в цепочку.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:kmp_pict2.png|640px]]&lt;br /&gt;
&lt;br /&gt;
==Псевдокод==&lt;br /&gt;
 '''int'''[] kmp('''string''' T, '''string''' P)&lt;br /&gt;
    '''int''' p = P.length&lt;br /&gt;
    '''int''' t = T.length&lt;br /&gt;
    '''int'''[] answer&lt;br /&gt;
    '''int'''[] &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt; = [[Префикс-функция#Эффективный_алгоритм|prefixFunction(P + &amp;quot;#&amp;quot; + T)]]&lt;br /&gt;
    count = 0&lt;br /&gt;
    '''for''' i = 0 .. (t - 1)&lt;br /&gt;
       '''if''' &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;[p + i + 1] == p&lt;br /&gt;
          answer[count++] = i + 1 - p&lt;br /&gt;
    '''return''' answer&lt;br /&gt;
&lt;br /&gt;
==Время работы==&lt;br /&gt;
Префикс-функция от строки &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; строится за &amp;lt;tex&amp;gt;O(S) = O(P + T)&amp;lt;/tex&amp;gt;. Проход цикла по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; содержит &amp;lt;tex&amp;gt;O(T)&amp;lt;/tex&amp;gt; итераций. Итого, время работы алгоритма оценивается как &amp;lt;tex&amp;gt;O(P + T)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Оценка по памяти==&lt;br /&gt;
Предложенная реализация имеет оценку по памяти &amp;lt;tex&amp;gt;O(P+T)&amp;lt;/tex&amp;gt;. Оценки &amp;lt;tex&amp;gt;O(P)&amp;lt;/tex&amp;gt; можно добиться за счет отказа от запоминания значений префикс-функции для позиций в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, меньших &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; (т.е. до начала цепочки &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;). Это возможно, так как значение префикс функции не может превысить длину образца, благодаря разделительному символу &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;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:ru:Алгоритм Кнута — Морриса — Пратта | Википедия {{---}} Алгоритм Кнута — Морриса — Пратта]]&lt;br /&gt;
*[[wikipedia:en:Knuth–Morris–Pratt algorithm | Wikipedia {{---}} Knuth–Morris–Pratt algorithm]]&lt;br /&gt;
*Кормен, Т., Лейзерсон, Ч., Ривест, Р., Штайн — Алгоритмы: построение и анализ / пер. с англ. — изд. 2-е — М.: Издательский дом «Вильямс», 2009. — с.1036. — ISBN 978-5-8459-0857-5.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Поиск подстроки в строке]]&lt;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%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=37403</id>
		<title>Алгоритм Кнута-Морриса-Пратта</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%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=37403"/>
				<updated>2014-05-30T19:28:55Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: Отмена правки 37399 участника 217.197.6.98 (обсуждение)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Алгоритм Кнута — Морриса — Пратта''' (англ. ''Knuth–Morris–Pratt algorithm'') — алгоритм [[Наивный алгоритм поиска подстроки в строке#Постановка задачи|поиска подстроки в строке]].&lt;br /&gt;
&lt;br /&gt;
==Описание алгоритма==&lt;br /&gt;
Дана цепочка &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; и образец &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;. Требуется найти все позиции, начиная с которых &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; входит в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Построим строку &amp;lt;tex&amp;gt;S = P\#T&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;gt; — любой символ, не входящий в алфавит &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;. Посчитаем на ней значение [[Префикс-функция|префикс-функции]]. Благодаря разделительному символу &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;gt;, выполняется &amp;lt;tex&amp;gt;\forall i: \pi(i) \leqslant |P|&amp;lt;/tex&amp;gt;. Заметим, что по определению [[Префикс-функция|префикс-функции]] при &amp;lt;tex&amp;gt;i &amp;gt; |P|&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\pi(i) = |P|&amp;lt;/tex&amp;gt; подстроки длины &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;, начинающиеся с позиций &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;i - |P| + 1&amp;lt;/tex&amp;gt;, совпадают. Соберем все такие позиции &amp;lt;tex&amp;gt;i - |P| + 1&amp;lt;/tex&amp;gt; строки &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, вычтем из каждой позиции &amp;lt;tex&amp;gt;|P| + 1&amp;lt;/tex&amp;gt;, это и будет ответ. Другими словами, если в какой-то позиции &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; выполняется условие &amp;lt;tex&amp;gt;\pi(i)=|P|&amp;lt;/tex&amp;gt;, то в этой позиции начинается очередное вхождение образца в цепочку.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:kmp_pict2.png|640px]]&lt;br /&gt;
&lt;br /&gt;
==Псевдокод==&lt;br /&gt;
 '''int'''[] kmp('''string''' T, '''string''' P)&lt;br /&gt;
    '''int''' p = P.length&lt;br /&gt;
    '''int''' t = T.length&lt;br /&gt;
    '''int'''[] answer&lt;br /&gt;
    count = 0&lt;br /&gt;
    '''for''' i = 0 .. (t - 1)&lt;br /&gt;
       '''if''' &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;(p + i + 1) == p&lt;br /&gt;
          answer[count++] = i + 1 - p&lt;br /&gt;
    '''return''' answer&lt;br /&gt;
&lt;br /&gt;
==Время работы==&lt;br /&gt;
Префикс-функция от строки &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; строится за &amp;lt;tex&amp;gt;O(S) = O(P + T)&amp;lt;/tex&amp;gt;. Проход цикла по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; содержит &amp;lt;tex&amp;gt;O(T)&amp;lt;/tex&amp;gt; итераций. Итого, время работы алгоритма оценивается как &amp;lt;tex&amp;gt;O(P + T)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Оценка по памяти==&lt;br /&gt;
Предложенная реализация имеет оценку по памяти &amp;lt;tex&amp;gt;O(P+T)&amp;lt;/tex&amp;gt;. Оценки &amp;lt;tex&amp;gt;O(P)&amp;lt;/tex&amp;gt; можно добиться за счет отказа от запоминания значений префикс-функции для позиций в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, меньших &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; (т.е. до начала цепочки &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;). Это возможно, так как значение префикс функции не может превысить длину образца, благодаря разделительному символу &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;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:ru:Алгоритм Кнута — Морриса — Пратта | Википедия {{---}} Алгоритм Кнута — Морриса — Пратта]]&lt;br /&gt;
*[[wikipedia:en:Knuth–Morris–Pratt algorithm | Wikipedia {{---}} Knuth–Morris–Pratt algorithm]]&lt;br /&gt;
*Кормен, Т., Лейзерсон, Ч., Ривест, Р., Штайн — Алгоритмы: построение и анализ / пер. с англ. — изд. 2-е — М.: Издательский дом «Вильямс», 2009. — с.1036. — ISBN 978-5-8459-0857-5.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Поиск подстроки в строке]]&lt;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%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=37402</id>
		<title>Алгоритм Кнута-Морриса-Пратта</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%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=37402"/>
				<updated>2014-05-30T19:28:38Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: Отмена правки 37401 участника 217.197.6.98 (обсуждение)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Алгоритм Кнута — Морриса — Пратта''' (англ. ''Knuth–Morris–Pratt algorithm'') — алгоритм [[Наивный алгоритм поиска подстроки в строке#Постановка задачи|поиска подстроки в строке]].&lt;br /&gt;
&lt;br /&gt;
==Описание алгоритма==&lt;br /&gt;
Дана цепочка &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; и образец &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;. Требуется найти все позиции, начиная с которых &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; входит в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Построим строку &amp;lt;tex&amp;gt;S = P\#T&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;gt; — любой символ, не входящий в алфавит &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;. Посчитаем на ней значение [[Префикс-функция|префикс-функции]]. Благодаря разделительному символу &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;gt;, выполняется &amp;lt;tex&amp;gt;\forall i: \pi(i) \leqslant |P|&amp;lt;/tex&amp;gt;. Заметим, что по определению [[Префикс-функция|префикс-функции]] при &amp;lt;tex&amp;gt;i &amp;gt; |P|&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\pi(i) = |P|&amp;lt;/tex&amp;gt; подстроки длины &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;, начинающиеся с позиций &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;i - |P| + 1&amp;lt;/tex&amp;gt;, совпадают. Соберем все такие позиции &amp;lt;tex&amp;gt;i - |P| + 1&amp;lt;/tex&amp;gt; строки &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, вычтем из каждой позиции &amp;lt;tex&amp;gt;|P| + 1&amp;lt;/tex&amp;gt;, это и будет ответ. Другими словами, если в какой-то позиции &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; выполняется условие &amp;lt;tex&amp;gt;\pi(i)=|P|&amp;lt;/tex&amp;gt;, то в этой позиции начинается очередное вхождение образца в цепочку.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:kmp_pict2.png|640px]]&lt;br /&gt;
&lt;br /&gt;
==Псевдокод==&lt;br /&gt;
 '''int'''[] kmp('''string''' T, '''string''' P)&lt;br /&gt;
    '''string''' S = P + &amp;quot;#&amp;quot; + T&lt;br /&gt;
    '''return''' [[Префикс-функция#Эффективный_алгоритм#Псевдокод|prefixFunction(S)]]&lt;br /&gt;
&lt;br /&gt;
==Время работы==&lt;br /&gt;
Префикс-функция от строки &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; строится за &amp;lt;tex&amp;gt;O(S) = O(P + T)&amp;lt;/tex&amp;gt;. Проход цикла по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; содержит &amp;lt;tex&amp;gt;O(T)&amp;lt;/tex&amp;gt; итераций. Итого, время работы алгоритма оценивается как &amp;lt;tex&amp;gt;O(P + T)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Оценка по памяти==&lt;br /&gt;
Предложенная реализация имеет оценку по памяти &amp;lt;tex&amp;gt;O(P+T)&amp;lt;/tex&amp;gt;. Оценки &amp;lt;tex&amp;gt;O(P)&amp;lt;/tex&amp;gt; можно добиться за счет отказа от запоминания значений префикс-функции для позиций в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, меньших &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; (т.е. до начала цепочки &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;). Это возможно, так как значение префикс функции не может превысить длину образца, благодаря разделительному символу &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;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:ru:Алгоритм Кнута — Морриса — Пратта | Википедия {{---}} Алгоритм Кнута — Морриса — Пратта]]&lt;br /&gt;
*[[wikipedia:en:Knuth–Morris–Pratt algorithm | Wikipedia {{---}} Knuth–Morris–Pratt algorithm]]&lt;br /&gt;
*Кормен, Т., Лейзерсон, Ч., Ривест, Р., Штайн — Алгоритмы: построение и анализ / пер. с англ. — изд. 2-е — М.: Издательский дом «Вильямс», 2009. — с.1036. — ISBN 978-5-8459-0857-5.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Поиск подстроки в строке]]&lt;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%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=37401</id>
		<title>Алгоритм Кнута-Морриса-Пратта</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%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=37401"/>
				<updated>2014-05-30T19:22:55Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Алгоритм Кнута — Морриса — Пратта''' (англ. ''Knuth–Morris–Pratt algorithm'') — алгоритм [[Наивный алгоритм поиска подстроки в строке#Постановка задачи|поиска подстроки в строке]].&lt;br /&gt;
&lt;br /&gt;
==Описание алгоритма==&lt;br /&gt;
Дана цепочка &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; и образец &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;. Требуется найти все позиции, начиная с которых &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; входит в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Построим строку &amp;lt;tex&amp;gt;S = P\#T&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;gt; — любой символ, не входящий в алфавит &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;. Посчитаем на ней значение [[Префикс-функция|префикс-функции]]. Благодаря разделительному символу &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;gt;, выполняется &amp;lt;tex&amp;gt;\forall i: \pi(i) \leqslant |P|&amp;lt;/tex&amp;gt;. Заметим, что по определению [[Префикс-функция|префикс-функции]] при &amp;lt;tex&amp;gt;i &amp;gt; |P|&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\pi(i) = |P|&amp;lt;/tex&amp;gt; подстроки длины &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;, начинающиеся с позиций &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;i - |P| + 1&amp;lt;/tex&amp;gt;, совпадают. Соберем все такие позиции &amp;lt;tex&amp;gt;i - |P| + 1&amp;lt;/tex&amp;gt; строки &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, вычтем из каждой позиции &amp;lt;tex&amp;gt;|P| + 1&amp;lt;/tex&amp;gt;, это и будет ответ. Другими словами, если в какой-то позиции &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; выполняется условие &amp;lt;tex&amp;gt;\pi(i)=|P|&amp;lt;/tex&amp;gt;, то в этой позиции начинается очередное вхождение образца в цепочку.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:kmp_pict2.png|640px]]&lt;br /&gt;
&lt;br /&gt;
==Псевдокод==&lt;br /&gt;
 '''int'''[] kmp('''string''' T, '''string''' P)&lt;br /&gt;
    '''string''' S = P + &amp;quot;#&amp;quot; + T&lt;br /&gt;
    '''return''' [[Префикс-функция#Эффективный_алгоритм|prefixFunction(S)]]&lt;br /&gt;
&lt;br /&gt;
==Время работы==&lt;br /&gt;
Префикс-функция от строки &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; строится за &amp;lt;tex&amp;gt;O(S) = O(P + T)&amp;lt;/tex&amp;gt;. Проход цикла по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; содержит &amp;lt;tex&amp;gt;O(T)&amp;lt;/tex&amp;gt; итераций. Итого, время работы алгоритма оценивается как &amp;lt;tex&amp;gt;O(P + T)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Оценка по памяти==&lt;br /&gt;
Предложенная реализация имеет оценку по памяти &amp;lt;tex&amp;gt;O(P+T)&amp;lt;/tex&amp;gt;. Оценки &amp;lt;tex&amp;gt;O(P)&amp;lt;/tex&amp;gt; можно добиться за счет отказа от запоминания значений префикс-функции для позиций в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, меньших &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; (т.е. до начала цепочки &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;). Это возможно, так как значение префикс функции не может превысить длину образца, благодаря разделительному символу &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;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:ru:Алгоритм Кнута — Морриса — Пратта | Википедия {{---}} Алгоритм Кнута — Морриса — Пратта]]&lt;br /&gt;
*[[wikipedia:en:Knuth–Morris–Pratt algorithm | Wikipedia {{---}} Knuth–Morris–Pratt algorithm]]&lt;br /&gt;
*Кормен, Т., Лейзерсон, Ч., Ривест, Р., Штайн — Алгоритмы: построение и анализ / пер. с англ. — изд. 2-е — М.: Издательский дом «Вильямс», 2009. — с.1036. — ISBN 978-5-8459-0857-5.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Поиск подстроки в строке]]&lt;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%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=37399</id>
		<title>Алгоритм Кнута-Морриса-Пратта</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%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=37399"/>
				<updated>2014-05-30T19:22:06Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Алгоритм Кнута — Морриса — Пратта''' (англ. ''Knuth–Morris–Pratt algorithm'') — алгоритм [[Наивный алгоритм поиска подстроки в строке#Постановка задачи|поиска подстроки в строке]].&lt;br /&gt;
&lt;br /&gt;
==Описание алгоритма==&lt;br /&gt;
Дана цепочка &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; и образец &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;. Требуется найти все позиции, начиная с которых &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; входит в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Построим строку &amp;lt;tex&amp;gt;S = P\#T&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;gt; — любой символ, не входящий в алфавит &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;. Посчитаем на ней значение [[Префикс-функция|префикс-функции]]. Благодаря разделительному символу &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;gt;, выполняется &amp;lt;tex&amp;gt;\forall i: \pi(i) \leqslant |P|&amp;lt;/tex&amp;gt;. Заметим, что по определению [[Префикс-функция|префикс-функции]] при &amp;lt;tex&amp;gt;i &amp;gt; |P|&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\pi(i) = |P|&amp;lt;/tex&amp;gt; подстроки длины &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;, начинающиеся с позиций &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;i - |P| + 1&amp;lt;/tex&amp;gt;, совпадают. Соберем все такие позиции &amp;lt;tex&amp;gt;i - |P| + 1&amp;lt;/tex&amp;gt; строки &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, вычтем из каждой позиции &amp;lt;tex&amp;gt;|P| + 1&amp;lt;/tex&amp;gt;, это и будет ответ. Другими словами, если в какой-то позиции &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; выполняется условие &amp;lt;tex&amp;gt;\pi(i)=|P|&amp;lt;/tex&amp;gt;, то в этой позиции начинается очередное вхождение образца в цепочку.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:kmp_pict2.png|640px]]&lt;br /&gt;
&lt;br /&gt;
==Псевдокод==&lt;br /&gt;
 '''int'''[] kmp('''string''' T, '''string''' P)&lt;br /&gt;
    '''string''' S = P + &amp;quot;#&amp;quot; + T&lt;br /&gt;
    '''return''' [[Префикс-функция#Эффективный_алгоритм#Псевдокод|prefixFunction(S)]]&lt;br /&gt;
&lt;br /&gt;
==Время работы==&lt;br /&gt;
Префикс-функция от строки &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; строится за &amp;lt;tex&amp;gt;O(S) = O(P + T)&amp;lt;/tex&amp;gt;. Проход цикла по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; содержит &amp;lt;tex&amp;gt;O(T)&amp;lt;/tex&amp;gt; итераций. Итого, время работы алгоритма оценивается как &amp;lt;tex&amp;gt;O(P + T)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Оценка по памяти==&lt;br /&gt;
Предложенная реализация имеет оценку по памяти &amp;lt;tex&amp;gt;O(P+T)&amp;lt;/tex&amp;gt;. Оценки &amp;lt;tex&amp;gt;O(P)&amp;lt;/tex&amp;gt; можно добиться за счет отказа от запоминания значений префикс-функции для позиций в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, меньших &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; (т.е. до начала цепочки &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;). Это возможно, так как значение префикс функции не может превысить длину образца, благодаря разделительному символу &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;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:ru:Алгоритм Кнута — Морриса — Пратта | Википедия {{---}} Алгоритм Кнута — Морриса — Пратта]]&lt;br /&gt;
*[[wikipedia:en:Knuth–Morris–Pratt algorithm | Wikipedia {{---}} Knuth–Morris–Pratt algorithm]]&lt;br /&gt;
*Кормен, Т., Лейзерсон, Ч., Ривест, Р., Штайн — Алгоритмы: построение и анализ / пер. с англ. — изд. 2-е — М.: Издательский дом «Вильямс», 2009. — с.1036. — ISBN 978-5-8459-0857-5.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Поиск подстроки в строке]]&lt;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%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=37398</id>
		<title>Алгоритм Кнута-Морриса-Пратта</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%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=37398"/>
				<updated>2014-05-30T19:17:21Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: /* Описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Алгоритм Кнута — Морриса — Пратта''' (англ. ''Knuth–Morris–Pratt algorithm'') — алгоритм [[Наивный алгоритм поиска подстроки в строке#Постановка задачи|поиска подстроки в строке]].&lt;br /&gt;
&lt;br /&gt;
==Описание алгоритма==&lt;br /&gt;
Дана цепочка &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; и образец &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;. Требуется найти все позиции, начиная с которых &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; входит в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Построим строку &amp;lt;tex&amp;gt;S = P\#T&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;gt; — любой символ, не входящий в алфавит &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;. Посчитаем на ней значение [[Префикс-функция|префикс-функции]]. Благодаря разделительному символу &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;gt;, выполняется &amp;lt;tex&amp;gt;\forall i: \pi(i) \leqslant |P|&amp;lt;/tex&amp;gt;. Заметим, что по определению [[Префикс-функция|префикс-функции]] при &amp;lt;tex&amp;gt;i &amp;gt; |P|&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\pi(i) = |P|&amp;lt;/tex&amp;gt; подстроки длины &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;, начинающиеся с позиций &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;i - |P| + 1&amp;lt;/tex&amp;gt;, совпадают. Соберем все такие позиции &amp;lt;tex&amp;gt;i - |P| + 1&amp;lt;/tex&amp;gt; строки &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, вычтем из каждой позиции &amp;lt;tex&amp;gt;|P| + 1&amp;lt;/tex&amp;gt;, это и будет ответ. Другими словами, если в какой-то позиции &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; выполняется условие &amp;lt;tex&amp;gt;\pi(i)=|P|&amp;lt;/tex&amp;gt;, то в этой позиции начинается очередное вхождение образца в цепочку.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:kmp_pict2.png|640px]]&lt;br /&gt;
&lt;br /&gt;
==Псевдокод==&lt;br /&gt;
 '''int'''[] kmp('''string''' T, '''string''' P)&lt;br /&gt;
    '''int''' p = P.length&lt;br /&gt;
    '''int''' t = T.length&lt;br /&gt;
    '''int'''[] answer&lt;br /&gt;
    count = 0&lt;br /&gt;
    '''for''' i = 0 .. (t - 1)&lt;br /&gt;
       '''if''' &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;(p + i + 1) == p&lt;br /&gt;
          answer[count++] = i + 1 - p&lt;br /&gt;
    '''return''' answer&lt;br /&gt;
&lt;br /&gt;
==Время работы==&lt;br /&gt;
Префикс-функция от строки &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; строится за &amp;lt;tex&amp;gt;O(S) = O(P + T)&amp;lt;/tex&amp;gt;. Проход цикла по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; содержит &amp;lt;tex&amp;gt;O(T)&amp;lt;/tex&amp;gt; итераций. Итого, время работы алгоритма оценивается как &amp;lt;tex&amp;gt;O(P + T)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Оценка по памяти==&lt;br /&gt;
Предложенная реализация имеет оценку по памяти &amp;lt;tex&amp;gt;O(P+T)&amp;lt;/tex&amp;gt;. Оценки &amp;lt;tex&amp;gt;O(P)&amp;lt;/tex&amp;gt; можно добиться за счет отказа от запоминания значений префикс-функции для позиций в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, меньших &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; (т.е. до начала цепочки &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;). Это возможно, так как значение префикс функции не может превысить длину образца, благодаря разделительному символу &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;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:ru:Алгоритм Кнута — Морриса — Пратта | Википедия {{---}} Алгоритм Кнута — Морриса — Пратта]]&lt;br /&gt;
*[[wikipedia:en:Knuth–Morris–Pratt algorithm | Wikipedia {{---}} Knuth–Morris–Pratt algorithm]]&lt;br /&gt;
*Кормен, Т., Лейзерсон, Ч., Ривест, Р., Штайн — Алгоритмы: построение и анализ / пер. с англ. — изд. 2-е — М.: Издательский дом «Вильямс», 2009. — с.1036. — ISBN 978-5-8459-0857-5.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Поиск подстроки в строке]]&lt;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%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=37397</id>
		<title>Алгоритм Кнута-Морриса-Пратта</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%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=37397"/>
				<updated>2014-05-30T19:16:44Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: /* Оценка по памяти */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Алгоритм Кнута — Морриса — Пратта''' (англ. ''Knuth–Morris–Pratt algorithm'') — алгоритм [[Наивный алгоритм поиска подстроки в строке#Постановка задачи|поиска подстроки в строке]].&lt;br /&gt;
&lt;br /&gt;
==Описание алгоритма==&lt;br /&gt;
Дана цепочка &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; и образец &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;. Требуется найти все позиции, начиная с которых &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; входит в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Построим строку &amp;lt;tex&amp;gt;S = P\#T&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;gt; — любой символ, не входящий в алфавит &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;. Посчитаем на ней [[Префикс-функция|префикс-функцию]] &amp;lt;tex&amp;gt;\pi()&amp;lt;/tex&amp;gt;. Благодаря разделительному символу &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;gt;, выполняется &amp;lt;tex&amp;gt;\forall i: \pi(i) \leqslant |P|&amp;lt;/tex&amp;gt;. Заметим, что по определению [[Префикс-функция|префикс-функции]] при &amp;lt;tex&amp;gt;i &amp;gt; |P|&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\pi(i) = |P|&amp;lt;/tex&amp;gt; подстроки длины &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;, начинающиеся с позиций &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;i - |P| + 1&amp;lt;/tex&amp;gt;, совпадают. Соберем все такие позиции &amp;lt;tex&amp;gt;i - |P| + 1&amp;lt;/tex&amp;gt; строки &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, вычтем из каждой позиции &amp;lt;tex&amp;gt;|P| + 1&amp;lt;/tex&amp;gt;, это и будет ответ. Другими словами, если в какой-то позиции &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; выполняется условие &amp;lt;tex&amp;gt;\pi(i)=|P|&amp;lt;/tex&amp;gt;, то в этой позиции начинается очередное вхождение образца в цепочку.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:kmp_pict2.png|640px]]&lt;br /&gt;
&lt;br /&gt;
==Псевдокод==&lt;br /&gt;
 '''int'''[] kmp('''string''' T, '''string''' P)&lt;br /&gt;
    '''int''' p = P.length&lt;br /&gt;
    '''int''' t = T.length&lt;br /&gt;
    '''int'''[] answer&lt;br /&gt;
    count = 0&lt;br /&gt;
    '''for''' i = 0 .. (t - 1)&lt;br /&gt;
       '''if''' &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;(p + i + 1) == p&lt;br /&gt;
          answer[count++] = i + 1 - p&lt;br /&gt;
    '''return''' answer&lt;br /&gt;
&lt;br /&gt;
==Время работы==&lt;br /&gt;
Префикс-функция от строки &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; строится за &amp;lt;tex&amp;gt;O(S) = O(P + T)&amp;lt;/tex&amp;gt;. Проход цикла по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; содержит &amp;lt;tex&amp;gt;O(T)&amp;lt;/tex&amp;gt; итераций. Итого, время работы алгоритма оценивается как &amp;lt;tex&amp;gt;O(P + T)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Оценка по памяти==&lt;br /&gt;
Предложенная реализация имеет оценку по памяти &amp;lt;tex&amp;gt;O(P+T)&amp;lt;/tex&amp;gt;. Оценки &amp;lt;tex&amp;gt;O(P)&amp;lt;/tex&amp;gt; можно добиться за счет отказа от запоминания значений префикс-функции для позиций в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, меньших &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; (т.е. до начала цепочки &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;). Это возможно, так как значение префикс функции не может превысить длину образца, благодаря разделительному символу &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;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:ru:Алгоритм Кнута — Морриса — Пратта | Википедия {{---}} Алгоритм Кнута — Морриса — Пратта]]&lt;br /&gt;
*[[wikipedia:en:Knuth–Morris–Pratt algorithm | Wikipedia {{---}} Knuth–Morris–Pratt algorithm]]&lt;br /&gt;
*Кормен, Т., Лейзерсон, Ч., Ривест, Р., Штайн — Алгоритмы: построение и анализ / пер. с англ. — изд. 2-е — М.: Издательский дом «Вильямс», 2009. — с.1036. — ISBN 978-5-8459-0857-5.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Поиск подстроки в строке]]&lt;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%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=37396</id>
		<title>Алгоритм Кнута-Морриса-Пратта</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%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=37396"/>
				<updated>2014-05-30T19:13:24Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: /* Оценка по памяти */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Алгоритм Кнута — Морриса — Пратта''' (англ. ''Knuth–Morris–Pratt algorithm'') — алгоритм [[Наивный алгоритм поиска подстроки в строке#Постановка задачи|поиска подстроки в строке]].&lt;br /&gt;
&lt;br /&gt;
==Описание алгоритма==&lt;br /&gt;
Дана цепочка &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; и образец &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;. Требуется найти все позиции, начиная с которых &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; входит в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Построим строку &amp;lt;tex&amp;gt;S = P\#T&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;gt; — любой символ, не входящий в алфавит &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;. Посчитаем на ней [[Префикс-функция|префикс-функцию]] &amp;lt;tex&amp;gt;\pi()&amp;lt;/tex&amp;gt;. Благодаря разделительному символу &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;gt;, выполняется &amp;lt;tex&amp;gt;\forall i: \pi(i) \leqslant |P|&amp;lt;/tex&amp;gt;. Заметим, что по определению [[Префикс-функция|префикс-функции]] при &amp;lt;tex&amp;gt;i &amp;gt; |P|&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\pi(i) = |P|&amp;lt;/tex&amp;gt; подстроки длины &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;, начинающиеся с позиций &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;i - |P| + 1&amp;lt;/tex&amp;gt;, совпадают. Соберем все такие позиции &amp;lt;tex&amp;gt;i - |P| + 1&amp;lt;/tex&amp;gt; строки &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, вычтем из каждой позиции &amp;lt;tex&amp;gt;|P| + 1&amp;lt;/tex&amp;gt;, это и будет ответ. Другими словами, если в какой-то позиции &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; выполняется условие &amp;lt;tex&amp;gt;\pi(i)=|P|&amp;lt;/tex&amp;gt;, то в этой позиции начинается очередное вхождение образца в цепочку.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:kmp_pict2.png|640px]]&lt;br /&gt;
&lt;br /&gt;
==Псевдокод==&lt;br /&gt;
 '''int'''[] kmp('''string''' T, '''string''' P)&lt;br /&gt;
    '''int''' p = P.length&lt;br /&gt;
    '''int''' t = T.length&lt;br /&gt;
    '''int'''[] answer&lt;br /&gt;
    count = 0&lt;br /&gt;
    '''for''' i = 0 .. (t - 1)&lt;br /&gt;
       '''if''' &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;(p + i + 1) == p&lt;br /&gt;
          answer[count++] = i + 1 - p&lt;br /&gt;
    '''return''' answer&lt;br /&gt;
&lt;br /&gt;
==Время работы==&lt;br /&gt;
Префикс-функция от строки &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; строится за &amp;lt;tex&amp;gt;O(S) = O(P + T)&amp;lt;/tex&amp;gt;. Проход цикла по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; содержит &amp;lt;tex&amp;gt;O(T)&amp;lt;/tex&amp;gt; итераций. Итого, время работы алгоритма оценивается как &amp;lt;tex&amp;gt;O(P + T)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Оценка по памяти==&lt;br /&gt;
Предложенная реализация имеет оценку по памяти &amp;lt;tex&amp;gt;O(P+T)&amp;lt;/tex&amp;gt;. Оценки &amp;lt;tex&amp;gt;O(T)&amp;lt;/tex&amp;gt; можно добиться за счет отказа от запоминания значений префикс-функции для позиций в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, меньших &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; (т.е. до начала цепочки &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;). Это возможно, так как значение префикс функции не может превысить длину образца, благодаря разделительному символу &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;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:ru:Алгоритм Кнута — Морриса — Пратта | Википедия {{---}} Алгоритм Кнута — Морриса — Пратта]]&lt;br /&gt;
*[[wikipedia:en:Knuth–Morris–Pratt algorithm | Wikipedia {{---}} Knuth–Morris–Pratt algorithm]]&lt;br /&gt;
*Кормен, Т., Лейзерсон, Ч., Ривест, Р., Штайн — Алгоритмы: построение и анализ / пер. с англ. — изд. 2-е — М.: Издательский дом «Вильямс», 2009. — с.1036. — ISBN 978-5-8459-0857-5.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Поиск подстроки в строке]]&lt;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%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=37393</id>
		<title>Алгоритм Кнута-Морриса-Пратта</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%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=37393"/>
				<updated>2014-05-30T18:54:14Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: /* Множественный поиск образцов */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Алгоритм Кнута — Морриса — Пратта''' (англ. ''Knuth–Morris–Pratt algorithm'') — алгоритм [[Наивный алгоритм поиска подстроки в строке#Постановка задачи|поиска подстроки в строке]].&lt;br /&gt;
&lt;br /&gt;
==Описание алгоритма==&lt;br /&gt;
Дана цепочка &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; и образец &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;. Требуется найти все позиции, начиная с которых &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; входит в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Построим строку &amp;lt;tex&amp;gt;S = P\#T&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;gt; — любой символ, не входящий в алфавит &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;. Посчитаем на ней [[Префикс-функция|префикс-функцию]] &amp;lt;tex&amp;gt;\pi()&amp;lt;/tex&amp;gt;. Благодаря разделительному символу &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;gt;, выполняется &amp;lt;tex&amp;gt;\forall i: \pi(i) \leqslant |P|&amp;lt;/tex&amp;gt;. Заметим, что по определению [[Префикс-функция|префикс-функции]] при &amp;lt;tex&amp;gt;i &amp;gt; |P|&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\pi(i) = |P|&amp;lt;/tex&amp;gt; подстроки длины &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;, начинающиеся с позиций &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;i - |P| + 1&amp;lt;/tex&amp;gt;, совпадают. Соберем все такие позиции &amp;lt;tex&amp;gt;i - |P| + 1&amp;lt;/tex&amp;gt; строки &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, вычтем из каждой позиции &amp;lt;tex&amp;gt;|P| + 1&amp;lt;/tex&amp;gt;, это и будет ответ. Другими словами, если в какой-то позиции &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; выполняется условие &amp;lt;tex&amp;gt;\pi(i)=|P|&amp;lt;/tex&amp;gt;, то в этой позиции начинается очередное вхождение образца в цепочку.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:kmp_pict2.png|640px]]&lt;br /&gt;
&lt;br /&gt;
==Псевдокод==&lt;br /&gt;
 '''int'''[] kmp('''string''' T, '''string''' P)&lt;br /&gt;
    '''int''' p = P.length&lt;br /&gt;
    '''int''' t = T.length&lt;br /&gt;
    '''int'''[] answer&lt;br /&gt;
    count = 0&lt;br /&gt;
    '''for''' i = 0 .. (t - 1)&lt;br /&gt;
       '''if''' &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;(p + i + 1) == p&lt;br /&gt;
          answer[count++] = i + 1 - p&lt;br /&gt;
    '''return''' answer&lt;br /&gt;
&lt;br /&gt;
==Множественный поиск образцов==&lt;br /&gt;
Если мы хотим произвести множественный поиск образцов в тексте, то для начала построим префикс-функции для всех образцов, а затем, при проходе по символам текста, будем сразу подсчитывать префикс-функции для каждого образца.&lt;br /&gt;
&lt;br /&gt;
==Время работы==&lt;br /&gt;
Префикс-функция от строки &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; строится за &amp;lt;tex&amp;gt;O(S) = O(P + T)&amp;lt;/tex&amp;gt;. Проход цикла по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; содержит &amp;lt;tex&amp;gt;O(T)&amp;lt;/tex&amp;gt; итераций. Итого, время работы алгоритма оценивается как &amp;lt;tex&amp;gt;O(P + T)&amp;lt;/tex&amp;gt;. Для множественного поиска общее время работы оценивается как &amp;lt;tex&amp;gt;O(Q + mT)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;{{---}} количество образцов, а &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; {{---}} суммарное время построения префикс-функций для всех образцов.&lt;br /&gt;
&lt;br /&gt;
==Оценка по памяти==&lt;br /&gt;
Предложенная реализация имеет оценку по памяти &amp;lt;tex&amp;gt;O(P+T)&amp;lt;/tex&amp;gt;. Оценки &amp;lt;tex&amp;gt;O(T)&amp;lt;/tex&amp;gt; можно добиться за счет отказа от запоминания значений префикс-функции для позиций в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, меньших &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; (т.е. до начала цепочки &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;), это возможно из-за того, что мы точно знаем, что значение префикс функции не может превысить длину образца, благодаря разделительному символу &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;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:ru:Алгоритм Кнута — Морриса — Пратта | Википедия {{---}} Алгоритм Кнута — Морриса — Пратта]]&lt;br /&gt;
*[[wikipedia:en:Knuth–Morris–Pratt algorithm | Wikipedia {{---}} Knuth–Morris–Pratt algorithm]]&lt;br /&gt;
*Кормен, Т., Лейзерсон, Ч., Ривест, Р., Штайн — Алгоритмы: построение и анализ / пер. с англ. — изд. 2-е — М.: Издательский дом «Вильямс», 2009. — с.1036. — ISBN 978-5-8459-0857-5.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Поиск подстроки в строке]]&lt;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%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=37392</id>
		<title>Алгоритм Кнута-Морриса-Пратта</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%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=37392"/>
				<updated>2014-05-30T18:52:42Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Алгоритм Кнута — Морриса — Пратта''' (англ. ''Knuth–Morris–Pratt algorithm'') — алгоритм [[Наивный алгоритм поиска подстроки в строке#Постановка задачи|поиска подстроки в строке]].&lt;br /&gt;
&lt;br /&gt;
==Описание алгоритма==&lt;br /&gt;
Дана цепочка &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; и образец &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;. Требуется найти все позиции, начиная с которых &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; входит в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Построим строку &amp;lt;tex&amp;gt;S = P\#T&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;gt; — любой символ, не входящий в алфавит &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;. Посчитаем на ней [[Префикс-функция|префикс-функцию]] &amp;lt;tex&amp;gt;\pi()&amp;lt;/tex&amp;gt;. Благодаря разделительному символу &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;gt;, выполняется &amp;lt;tex&amp;gt;\forall i: \pi(i) \leqslant |P|&amp;lt;/tex&amp;gt;. Заметим, что по определению [[Префикс-функция|префикс-функции]] при &amp;lt;tex&amp;gt;i &amp;gt; |P|&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\pi(i) = |P|&amp;lt;/tex&amp;gt; подстроки длины &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;, начинающиеся с позиций &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;i - |P| + 1&amp;lt;/tex&amp;gt;, совпадают. Соберем все такие позиции &amp;lt;tex&amp;gt;i - |P| + 1&amp;lt;/tex&amp;gt; строки &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, вычтем из каждой позиции &amp;lt;tex&amp;gt;|P| + 1&amp;lt;/tex&amp;gt;, это и будет ответ. Другими словами, если в какой-то позиции &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; выполняется условие &amp;lt;tex&amp;gt;\pi(i)=|P|&amp;lt;/tex&amp;gt;, то в этой позиции начинается очередное вхождение образца в цепочку.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:kmp_pict2.png|640px]]&lt;br /&gt;
&lt;br /&gt;
==Псевдокод==&lt;br /&gt;
 '''int'''[] kmp('''string''' T, '''string''' P)&lt;br /&gt;
    '''int''' p = P.length&lt;br /&gt;
    '''int''' t = T.length&lt;br /&gt;
    '''int'''[] answer&lt;br /&gt;
    count = 0&lt;br /&gt;
    '''for''' i = 0 .. (t - 1)&lt;br /&gt;
       '''if''' &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;(p + i + 1) == p&lt;br /&gt;
          answer[count++] = i + 1 - p&lt;br /&gt;
    '''return''' answer&lt;br /&gt;
&lt;br /&gt;
==Множественный поиск образцов==&lt;br /&gt;
Если мы хотим произвести множественный поиск образцов в тексте, то нам необходимо хранить значение префикс-функции символа текста для каждого образца. Перед этим нужно построить префикс-функции для всех образцов.&lt;br /&gt;
&lt;br /&gt;
==Время работы==&lt;br /&gt;
Префикс-функция от строки &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; строится за &amp;lt;tex&amp;gt;O(S) = O(P + T)&amp;lt;/tex&amp;gt;. Проход цикла по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; содержит &amp;lt;tex&amp;gt;O(T)&amp;lt;/tex&amp;gt; итераций. Итого, время работы алгоритма оценивается как &amp;lt;tex&amp;gt;O(P + T)&amp;lt;/tex&amp;gt;. Для множественного поиска общее время работы оценивается как &amp;lt;tex&amp;gt;O(Q + mT)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;{{---}} количество образцов, а &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; {{---}} суммарное время построения префикс-функций для всех образцов.&lt;br /&gt;
&lt;br /&gt;
==Оценка по памяти==&lt;br /&gt;
Предложенная реализация имеет оценку по памяти &amp;lt;tex&amp;gt;O(P+T)&amp;lt;/tex&amp;gt;. Оценки &amp;lt;tex&amp;gt;O(T)&amp;lt;/tex&amp;gt; можно добиться за счет отказа от запоминания значений префикс-функции для позиций в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, меньших &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; (т.е. до начала цепочки &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;), это возможно из-за того, что мы точно знаем, что значение префикс функции не может превысить длину образца, благодаря разделительному символу &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;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:ru:Алгоритм Кнута — Морриса — Пратта | Википедия {{---}} Алгоритм Кнута — Морриса — Пратта]]&lt;br /&gt;
*[[wikipedia:en:Knuth–Morris–Pratt algorithm | Wikipedia {{---}} Knuth–Morris–Pratt algorithm]]&lt;br /&gt;
*Кормен, Т., Лейзерсон, Ч., Ривест, Р., Штайн — Алгоритмы: построение и анализ / пер. с англ. — изд. 2-е — М.: Издательский дом «Вильямс», 2009. — с.1036. — ISBN 978-5-8459-0857-5.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Поиск подстроки в строке]]&lt;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%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=37391</id>
		<title>Алгоритм Кнута-Морриса-Пратта</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%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=37391"/>
				<updated>2014-05-30T18:47:51Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Алгоритм Кнута — Морриса — Пратта''' (англ. ''Knuth–Morris–Pratt algorithm'') — алгоритм [[Наивный алгоритм поиска подстроки в строке#Постановка задачи|поиска подстроки в строке]].&lt;br /&gt;
&lt;br /&gt;
==Описание алгоритма==&lt;br /&gt;
Дана цепочка &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; и образец &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;. Требуется найти все позиции, начиная с которых &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; входит в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Построим строку &amp;lt;tex&amp;gt;S = P\#T&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;gt; — любой символ, не входящий в алфавит &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;. Посчитаем на ней [[Префикс-функция|префикс-функцию]] &amp;lt;tex&amp;gt;\pi()&amp;lt;/tex&amp;gt;. Благодаря разделительному символу &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;gt;, выполняется &amp;lt;tex&amp;gt;\forall i: \pi(i) \leqslant |P|&amp;lt;/tex&amp;gt;. Заметим, что по определению [[Префикс-функция|префикс-функции]] при &amp;lt;tex&amp;gt;i &amp;gt; |P|&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\pi(i) = |P|&amp;lt;/tex&amp;gt; подстроки длины &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;, начинающиеся с позиций &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;i - |P| + 1&amp;lt;/tex&amp;gt;, совпадают. Соберем все такие позиции &amp;lt;tex&amp;gt;i - |P| + 1&amp;lt;/tex&amp;gt; строки &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, вычтем из каждой позиции &amp;lt;tex&amp;gt;|P| + 1&amp;lt;/tex&amp;gt;, это и будет ответ. Другими словами, если в какой-то позиции &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; выполняется условие &amp;lt;tex&amp;gt;\pi(i)=|P|&amp;lt;/tex&amp;gt;, то в этой позиции начинается очередное вхождение образца в цепочку.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:kmp_pict2.png|640px]]&lt;br /&gt;
&lt;br /&gt;
==Псевдокод==&lt;br /&gt;
 '''int'''[] kmp('''string''' T, '''string''' P)&lt;br /&gt;
    '''int''' p = P.length&lt;br /&gt;
    '''int''' t = T.length&lt;br /&gt;
    '''int'''[] answer&lt;br /&gt;
    count = 0&lt;br /&gt;
    '''for''' i = 0 .. (t - 1)&lt;br /&gt;
       '''if''' &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;(p + i + 1) == p&lt;br /&gt;
          answer[count++] = i + 1 - p&lt;br /&gt;
    '''return''' answer&lt;br /&gt;
&lt;br /&gt;
==Время работы==&lt;br /&gt;
Префикс-функция от строки &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; строится за &amp;lt;tex&amp;gt;O(S) = O(P + T)&amp;lt;/tex&amp;gt;. Проход цикла по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; содержит &amp;lt;tex&amp;gt;O(T)&amp;lt;/tex&amp;gt; итераций. Итого, время работы алгоритма оценивается как &amp;lt;tex&amp;gt;O(P + T)&amp;lt;/tex&amp;gt;. Если мы хотим произвести множественный поиск образцов в тексте, то необходимо построить префикс-функцию для каждого из образцов в отдельности, тогда, учитывая, что длина образца обычно много меньше, чем длина текста, то общее время работы оценивается как &amp;lt;tex&amp;gt;O(mT)&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;O(P+T)&amp;lt;/tex&amp;gt;. Оценки &amp;lt;tex&amp;gt;O(T)&amp;lt;/tex&amp;gt; можно добиться за счет отказа от запоминания значений префикс-функции для позиций в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, меньших &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; (т.е. до начала цепочки &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;), это возможно из-за того, что мы точно знаем, что значение префикс функции не может превысить длину образца, благодаря разделительному символу &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;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:ru:Алгоритм Кнута — Морриса — Пратта | Википедия {{---}} Алгоритм Кнута — Морриса — Пратта]]&lt;br /&gt;
*[[wikipedia:en:Knuth–Morris–Pratt algorithm | Wikipedia {{---}} Knuth–Morris–Pratt algorithm]]&lt;br /&gt;
*Кормен, Т., Лейзерсон, Ч., Ривест, Р., Штайн — Алгоритмы: построение и анализ / пер. с англ. — изд. 2-е — М.: Издательский дом «Вильямс», 2009. — с.1036. — ISBN 978-5-8459-0857-5.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Поиск подстроки в строке]]&lt;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%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=37382</id>
		<title>Алгоритм Кнута-Морриса-Пратта</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%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=37382"/>
				<updated>2014-05-30T15:09:48Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Алгоритм Кнута — Морриса — Пратта''' (англ. ''Knuth–Morris–Pratt algorithm'') — алгоритм [[Наивный алгоритм поиска подстроки в строке#Постановка задачи|поиска подстроки в строке]].&lt;br /&gt;
&lt;br /&gt;
==Описание алгоритма==&lt;br /&gt;
Дана цепочка &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; и образец &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;. Требуется найти все позиции, начиная с которых &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; входит в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Построим строку &amp;lt;tex&amp;gt;S = P\#T&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;gt; — любой символ, не входящий в алфавит &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;. Посчитаем на ней [[Префикс-функция|префикс-функцию]] &amp;lt;tex&amp;gt;\pi()&amp;lt;/tex&amp;gt;. Благодаря разделительному символу &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;gt;, выполняется &amp;lt;tex&amp;gt;\forall i: \pi(i) \le |P|&amp;lt;/tex&amp;gt;. Заметим, что по определению [[Префикс-функция|префикс-функции]] при &amp;lt;tex&amp;gt;i &amp;gt; |P|&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\pi(i) = |P|&amp;lt;/tex&amp;gt; подстроки длины &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;, начинающиеся с позиций &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;i - |P| + 1&amp;lt;/tex&amp;gt;, совпадают. Соберем все такие позиции &amp;lt;tex&amp;gt;i - |P| + 1&amp;lt;/tex&amp;gt; строки &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, вычтем из каждой позиции &amp;lt;tex&amp;gt;|P| + 1&amp;lt;/tex&amp;gt;, это и будет ответ.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:kmp_pict.png|640px]]&lt;br /&gt;
&lt;br /&gt;
==Псевдокод==&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;p = |P|&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;t = |T|&amp;lt;/tex&amp;gt;.&lt;br /&gt;
 count = 0&lt;br /&gt;
 '''for''' (i = 0 .. (t - 1))&lt;br /&gt;
    '''if''' (&amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;(p + i + 1) == p)&lt;br /&gt;
       answer[count++] = i + 1 - p&lt;br /&gt;
&lt;br /&gt;
==Время работы==&lt;br /&gt;
Префикс-функция от строки &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; строится за &amp;lt;tex&amp;gt;O(S) = O(P + T)&amp;lt;/tex&amp;gt;. Проход цикла по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; содержит &amp;lt;tex&amp;gt;O(T)&amp;lt;/tex&amp;gt; итераций. Итого, время работы алгоритма оценивается как &amp;lt;tex&amp;gt;O(P + T)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Оценка по памяти==&lt;br /&gt;
Предложенная реализация имеет оценку по памяти &amp;lt;tex&amp;gt;O(P+T)&amp;lt;/tex&amp;gt;. Оценки &amp;lt;tex&amp;gt;O(T)&amp;lt;/tex&amp;gt; можно добиться за счет незапоминания значений &amp;lt;tex&amp;gt;\pi()&amp;lt;/tex&amp;gt; для позиций в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, меньших &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; (т.е. до начала цепочки &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==Источники==&lt;br /&gt;
*[[wikipedia:ru:Алгоритм Кнута — Морриса — Пратта | Википедия {{---}} Алгоритм Кнута — Морриса — Пратта]]&lt;br /&gt;
*[[wikipedia:en:Knuth–Morris–Pratt algorithm | Wikipedia {{---}} Knuth–Morris–Pratt algorithm]]&lt;br /&gt;
*Кормен, Т., Лейзерсон, Ч., Ривест, Р., Штайн — Алгоритмы: построение и анализ / пер. с англ. — изд. 2-е — М.: Издательский дом «Вильямс», 2009. — с.1036. — ISBN 978-5-8459-0857-5.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Поиск подстроки в строке]]&lt;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%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=37381</id>
		<title>Алгоритм Кнута-Морриса-Пратта</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%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=37381"/>
				<updated>2014-05-30T15:08:08Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: /* Источники */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Алгоритм Кнута — Морриса — Пратта — алгоритм [[Наивный алгоритм поиска подстроки в строке#Постановка задачи|поиска подстроки в строке]].&lt;br /&gt;
&lt;br /&gt;
==Описание алгоритма==&lt;br /&gt;
Дана цепочка &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; и образец &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;. Требуется найти все позиции, начиная с которых &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; входит в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Построим строку &amp;lt;tex&amp;gt;S = P\#T&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;gt; — любой символ, не входящий в алфавит &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;. Посчитаем на ней [[Префикс-функция|префикс-функцию]] &amp;lt;tex&amp;gt;\pi()&amp;lt;/tex&amp;gt;. Благодаря разделительному символу &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;gt;, выполняется &amp;lt;tex&amp;gt;\forall i: \pi(i) \le |P|&amp;lt;/tex&amp;gt;. Заметим, что по определению [[Префикс-функция|префикс-функции]] при &amp;lt;tex&amp;gt;i &amp;gt; |P|&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\pi(i) = |P|&amp;lt;/tex&amp;gt; подстроки длины &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;, начинающиеся с позиций &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;i - |P| + 1&amp;lt;/tex&amp;gt;, совпадают. Соберем все такие позиции &amp;lt;tex&amp;gt;i - |P| + 1&amp;lt;/tex&amp;gt; строки &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, вычтем из каждой позиции &amp;lt;tex&amp;gt;|P| + 1&amp;lt;/tex&amp;gt;, это и будет ответ.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:kmp_pict.png|640px]]&lt;br /&gt;
&lt;br /&gt;
==Псевдокод==&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;p = |P|&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;t = |T|&amp;lt;/tex&amp;gt;.&lt;br /&gt;
 count = 0&lt;br /&gt;
 '''for''' (i = 0 .. (t - 1))&lt;br /&gt;
    '''if''' (&amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;(p + i + 1) == p)&lt;br /&gt;
       answer[count++] = i + 1 - p&lt;br /&gt;
&lt;br /&gt;
==Время работы==&lt;br /&gt;
Префикс-функция от строки &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; строится за &amp;lt;tex&amp;gt;O(S) = O(P + T)&amp;lt;/tex&amp;gt;. Проход цикла по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; содержит &amp;lt;tex&amp;gt;O(T)&amp;lt;/tex&amp;gt; итераций. Итого, время работы алгоритма оценивается как &amp;lt;tex&amp;gt;O(P + T)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Оценка по памяти==&lt;br /&gt;
Предложенная реализация имеет оценку по памяти &amp;lt;tex&amp;gt;O(P+T)&amp;lt;/tex&amp;gt;. Оценки &amp;lt;tex&amp;gt;O(T)&amp;lt;/tex&amp;gt; можно добиться за счет незапоминания значений &amp;lt;tex&amp;gt;\pi()&amp;lt;/tex&amp;gt; для позиций в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, меньших &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; (т.е. до начала цепочки &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==Источники==&lt;br /&gt;
*[[wikipedia:ru:Алгоритм Кнута — Морриса — Пратта | Википедия {{---}} Алгоритм Кнута — Морриса — Пратта]]&lt;br /&gt;
*[[wikipedia:en:Knuth–Morris–Pratt algorithm | Wikipedia {{---}} Knuth–Morris–Pratt algorithm]]&lt;br /&gt;
*Кормен, Т., Лейзерсон, Ч., Ривест, Р., Штайн — Алгоритмы: построение и анализ / пер. с англ. — изд. 2-е — М.: Издательский дом «Вильямс», 2009. — с.1036. — ISBN 978-5-8459-0857-5.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Поиск подстроки в строке]]&lt;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%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=37380</id>
		<title>Алгоритм Кнута-Морриса-Пратта</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%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=37380"/>
				<updated>2014-05-30T15:05:51Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: /* Источники */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Алгоритм Кнута — Морриса — Пратта — алгоритм [[Наивный алгоритм поиска подстроки в строке#Постановка задачи|поиска подстроки в строке]].&lt;br /&gt;
&lt;br /&gt;
==Описание алгоритма==&lt;br /&gt;
Дана цепочка &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; и образец &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;. Требуется найти все позиции, начиная с которых &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; входит в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Построим строку &amp;lt;tex&amp;gt;S = P\#T&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;gt; — любой символ, не входящий в алфавит &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;. Посчитаем на ней [[Префикс-функция|префикс-функцию]] &amp;lt;tex&amp;gt;\pi()&amp;lt;/tex&amp;gt;. Благодаря разделительному символу &amp;lt;tex&amp;gt;\#&amp;lt;/tex&amp;gt;, выполняется &amp;lt;tex&amp;gt;\forall i: \pi(i) \le |P|&amp;lt;/tex&amp;gt;. Заметим, что по определению [[Префикс-функция|префикс-функции]] при &amp;lt;tex&amp;gt;i &amp;gt; |P|&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\pi(i) = |P|&amp;lt;/tex&amp;gt; подстроки длины &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;, начинающиеся с позиций &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;i - |P| + 1&amp;lt;/tex&amp;gt;, совпадают. Соберем все такие позиции &amp;lt;tex&amp;gt;i - |P| + 1&amp;lt;/tex&amp;gt; строки &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, вычтем из каждой позиции &amp;lt;tex&amp;gt;|P| + 1&amp;lt;/tex&amp;gt;, это и будет ответ.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:kmp_pict.png|640px]]&lt;br /&gt;
&lt;br /&gt;
==Псевдокод==&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;p = |P|&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;t = |T|&amp;lt;/tex&amp;gt;.&lt;br /&gt;
 count = 0&lt;br /&gt;
 '''for''' (i = 0 .. (t - 1))&lt;br /&gt;
    '''if''' (&amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;(p + i + 1) == p)&lt;br /&gt;
       answer[count++] = i + 1 - p&lt;br /&gt;
&lt;br /&gt;
==Время работы==&lt;br /&gt;
Префикс-функция от строки &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; строится за &amp;lt;tex&amp;gt;O(S) = O(P + T)&amp;lt;/tex&amp;gt;. Проход цикла по строке &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; содержит &amp;lt;tex&amp;gt;O(T)&amp;lt;/tex&amp;gt; итераций. Итого, время работы алгоритма оценивается как &amp;lt;tex&amp;gt;O(P + T)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Оценка по памяти==&lt;br /&gt;
Предложенная реализация имеет оценку по памяти &amp;lt;tex&amp;gt;O(P+T)&amp;lt;/tex&amp;gt;. Оценки &amp;lt;tex&amp;gt;O(T)&amp;lt;/tex&amp;gt; можно добиться за счет незапоминания значений &amp;lt;tex&amp;gt;\pi()&amp;lt;/tex&amp;gt; для позиций в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, меньших &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; (т.е. до начала цепочки &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==Источники==&lt;br /&gt;
[http://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm Knuth–Morris–Pratt algorithm]&amp;lt;br&amp;gt;&lt;br /&gt;
Кормен, Т., Лейзерсон, Ч., Ривест, Р., Штайн — Алгоритмы: построение и анализ / пер. с англ. — изд. 2-е — М.: Издательский дом «Вильямс», 2009. — с.1036. — ISBN 978-5-8459-0857-5.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Поиск подстроки в строке]]&lt;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B5%D1%84%D0%B8%D0%BA%D1%81-%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D1%8F&amp;diff=36999</id>
		<title>Префикс-функция</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B5%D1%84%D0%B8%D0%BA%D1%81-%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D1%8F&amp;diff=36999"/>
				<updated>2014-05-14T14:36:31Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition = '''Префикс-функция''' ''(англ. prefix-function)'' от строки {{---}} длина наибольшего [[Период_и_бордер,_их_связь#Определения|бордера]] этой строки}}&lt;br /&gt;
Здесь и далее считаем, что символы в строках нумеруются с &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Определим префикс-функцию от строки &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; в позиции &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; следующим образом: &amp;lt;tex&amp;gt;\pi(s, i) = \max\limits_{k = 1..i - 1} \{k : &amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;s[1..k] = s[i - k + 1..i] \}&amp;lt;/tex&amp;gt;. Если мы не нашли такого &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\pi(s, i)=0&amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
==Наивный алгоритм==&lt;br /&gt;
Наивный алгоритм вычисляет префикс функцию непосредственно по определению, сравнивая префиксы и суффиксы строк. Обозначим длину строки за &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
 '''Prefix_function''' (&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;)&lt;br /&gt;
      fill(&amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;, 0)&lt;br /&gt;
      '''for''' i = 1 '''to''' n&lt;br /&gt;
          '''for''' k = 1 '''to''' i&lt;br /&gt;
              '''if''' s[1..k] == s[i - k + 1..i])&lt;br /&gt;
                  &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;[i] = k&lt;br /&gt;
      '''return''' &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
Рассмотрим строку abcabcd, для которой значение префикс-функции равно &amp;lt;tex&amp;gt;[0,0,0,1,2,3,0]&amp;lt;/tex&amp;gt;.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Шаг || Строка || Значение функции&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; || a || 0&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; || ab || 0&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt; || abc || 0&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt; || abca || 1&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt; || abcab || 2&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;6&amp;lt;/tex&amp;gt; || abcabc || 3&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;7&amp;lt;/tex&amp;gt; || abcabcd || 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Время работы===&lt;br /&gt;
Всего &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; итераций цикла, на каждой из который происходит сравнение строк за &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;, что дает в итоге &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Эффективный алгоритм==&lt;br /&gt;
Вносятся несколько важных замечаний:&lt;br /&gt;
*Заметим, что &amp;lt;tex&amp;gt;\pi[i + 1] \leqslant \pi[i] + 1&amp;lt;/tex&amp;gt;. Чтобы показать это, рассмотрим суффикс,оканчивающийся на позиции &amp;lt;tex&amp;gt;i + 1&amp;lt;/tex&amp;gt; и имеющий длину &amp;lt;tex&amp;gt;\pi[i + 1]&amp;lt;/tex&amp;gt;, удалив из него последний символ, мы получим суффикс, оканчивающийся на позиции &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; и имеющий длину &amp;lt;tex&amp;gt;\pi[i + 1] - 1&amp;lt;/tex&amp;gt;, следовательно неравенство &amp;lt;tex&amp;gt;\pi[i + 1] &amp;gt; \pi[i] + 1&amp;lt;/tex&amp;gt; неверно.&lt;br /&gt;
*Избавимся от явных сравнений строк. &lt;br /&gt;
**Пусть мы вычислили &amp;lt;tex&amp;gt;\pi[i]&amp;lt;/tex&amp;gt;, тогда, если &amp;lt;tex&amp;gt;s[i + 1] = s[\pi[i]]&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\pi[i + 1] = \pi[i] + 1&amp;lt;/tex&amp;gt;. &lt;br /&gt;
**Если окажется, что &amp;lt;tex&amp;gt;s[i + 1] \ne s[\pi[i]]&amp;lt;/tex&amp;gt;, то нужно попытаться попробовать подстроку меньшей длины. Хотелось бы сразу перейти к такому [[Период_и_бордер,_их_связь#Определения|бордеру]] наибольшей длины, для этого подберем такое &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;, что &amp;lt;tex&amp;gt;k = \pi(i) - 1&amp;lt;/tex&amp;gt;. Делаем это следующим образом. За исходное &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; необходимо взять &amp;lt;tex&amp;gt;\pi(i - 1)&amp;lt;/tex&amp;gt;, что следует из первого пункта. В случае, когда символы &amp;lt;tex&amp;gt;s[k+1]&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;s[i]&amp;lt;/tex&amp;gt; не совпадают, &amp;lt;tex&amp;gt;\pi(k)&amp;lt;/tex&amp;gt; {{---}} следующее потенциальное наибольшее значение &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;, что видно из рисунка. Последнее утверждение верно, пока &amp;lt;tex&amp;gt;k&amp;gt;0&amp;lt;/tex&amp;gt;, что позволит всегда найти его следующее значение. Если &amp;lt;tex&amp;gt;k=0&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\pi(i)=1&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;s[i] = s[1]&amp;lt;/tex&amp;gt; , иначе &amp;lt;tex&amp;gt;\pi(i)=0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Prfx.jpg‎]]&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
 '''Prefix_function''' (&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;)&lt;br /&gt;
      &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;[1] = 0&lt;br /&gt;
      '''for''' i = 2 '''to''' n&lt;br /&gt;
          k = &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;[i-1]&lt;br /&gt;
          '''while''' k &amp;gt; 0 &amp;amp;&amp;amp; s[i] != s[k + 1] &lt;br /&gt;
              k = &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;[k]&lt;br /&gt;
          '''if''' s[i] == s[k + 1]&lt;br /&gt;
              k++&lt;br /&gt;
          &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;[i] = k&lt;br /&gt;
      '''return''' &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Время работы===&lt;br /&gt;
Время работы алгоритма составит &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для доказательства этого нужно заметить, что итоговое количество итераций цикла &amp;lt;tex&amp;gt;while&amp;lt;/tex&amp;gt; определяет асимптотику алгоритма. Теперь стоит отметить, что &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; увеличивается на каждом шаге не более чем на единицу, значит максимально возможное значение &amp;lt;tex&amp;gt;k = n - 1&amp;lt;/tex&amp;gt;. Поскольку внутри цикла &amp;lt;tex&amp;gt;while&amp;lt;/tex&amp;gt; значение &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; лишь уменьшается, получается, что &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; не может суммарно уменьшиться больше, чем &amp;lt;tex&amp;gt;n-1&amp;lt;/tex&amp;gt; раз. Значит цикл &amp;lt;tex&amp;gt;while&amp;lt;/tex&amp;gt; в итоге выполнится не более &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; раз, что дает итоговую оценку времени алгоритма &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Построение строки по префикс-функции==&lt;br /&gt;
===Постановка задачи=== &lt;br /&gt;
Восстановить строку по префикс-функции за &amp;lt;tex&amp;gt;O(N)&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;s&amp;lt;/tex&amp;gt; будет записан ответ. Пойдем по массиву &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; слева направо.&lt;br /&gt;
&lt;br /&gt;
Пусть мы хотим узнать значение &amp;lt;tex&amp;gt;s[i]&amp;lt;/tex&amp;gt;. Для этого посмотрим на значение &amp;lt;tex&amp;gt;p[i]&amp;lt;/tex&amp;gt;: если &amp;lt;tex&amp;gt;p[i] =0&amp;lt;/tex&amp;gt; тогда в &amp;lt;tex&amp;gt;s[i]&amp;lt;/tex&amp;gt; запишем новый символ, иначе &amp;lt;tex&amp;gt;s[i] = s[p[i]]&amp;lt;/tex&amp;gt;. Обратим внимание, что  &amp;lt;tex&amp;gt;s[p[i]]&amp;lt;/tex&amp;gt; нам уже известно, так как &amp;lt;tex&amp;gt;p[i] &amp;lt; i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Реализация ===&lt;br /&gt;
 '''string''' buildFromPrefix('''int'''[] p):&lt;br /&gt;
   s = &amp;quot;&amp;quot; &lt;br /&gt;
   '''for''' i = 0 '''to''' p.length - 1&lt;br /&gt;
       '''if''' p[i] == 0     &lt;br /&gt;
           s += new character&lt;br /&gt;
       '''else'''&lt;br /&gt;
           s += s[p[i]]&lt;br /&gt;
   '''return''' s&lt;br /&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;s'&amp;lt;/tex&amp;gt; правильная строка, строку &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; построил наш алгоритм, &amp;lt;tex&amp;gt; q &amp;lt;/tex&amp;gt; массив значений префикс-функции для &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Докажем корректность индукцией по длине массива префикс-функции полученной строки. Для начала заметим, что на предыдущие значения массива &amp;lt;tex&amp;gt; q &amp;lt;/tex&amp;gt; прибавление нового символа не влияет, так как при подсчёте префикс-функции на &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;-ой позиции рассматриваются символы на позициях не больше &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;. Поэтому достаточно показать, что очередное значение префикс-функции будет вычислено правильно.&lt;br /&gt;
* База очевидна для строки длины &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* Переход: пусть до &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;-ой позиции мы построили строку, что &amp;lt;tex&amp;gt;p[1..n - 1] = q[1..n - 1]&amp;lt;/tex&amp;gt;. Возможны два случая:&lt;br /&gt;
**  &amp;lt;tex&amp;gt;p[n] = 0&amp;lt;/tex&amp;gt;. Тогда мы добавляем новый символ, поэтому &amp;lt;tex&amp;gt;q[n]&amp;lt;/tex&amp;gt; тоже будет равно &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;. &lt;br /&gt;
** &amp;lt;tex&amp;gt;p[n] &amp;gt; 0&amp;lt;/tex&amp;gt;. По свойствам префикс-функции &amp;lt;tex&amp;gt; s'[p[n]] = s'[n] &amp;lt;/tex&amp;gt; {{---}} суффикс и префикс строки &amp;lt;tex&amp;gt; s' &amp;lt;/tex&amp;gt; длины &amp;lt;tex&amp;gt; p[n] &amp;lt;/tex&amp;gt; продолжаются одним символом, значит, надо на текущую позицию строки &amp;lt;tex&amp;gt; s &amp;lt;/tex&amp;gt; поставить символ &amp;lt;tex&amp;gt; s[p[n]] &amp;lt;/tex&amp;gt;. Если значение префикс-функции увеличивается, значит, текущим символом продолжается префикс длины &amp;lt;tex&amp;gt; p[n - 1] &amp;lt;/tex&amp;gt;, а из свойств следует, что &amp;lt;tex&amp;gt; p[n - 1] \geqslant p[n] - 1 &amp;lt;/tex&amp;gt;. По предположению индукцию значение &amp;lt;tex&amp;gt; q[n - 1] &amp;lt;/tex&amp;gt; будет вычислено верно. А если значение префикс-функции не увеличивается, значит, символ &amp;lt;tex&amp;gt; s[n] &amp;lt;/tex&amp;gt; должен продолжить префикс меньшей длины, а в текущее значение префикс-функции запишется как раз длина нового [[Период_и_бордер,_их_связь#Определения|бордера]]. Для этого будут использованы значения префикс-функции с меньшими индексами, которые посчитаны верно, опять же по предположению индукции.&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Кормен Т., Лейзерсон Ч., Ривест Р. Алгоритмы: построение и анализ. {{---}} 2-е изд. {{---}} М.: Издательский дом «Вильямс», 2007. {{---}} С. 1296 ISBN 978-5-8459-0857-5&lt;br /&gt;
*&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Поиск подстроки в строке]]&lt;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B5%D1%84%D0%B8%D0%BA%D1%81-%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D1%8F&amp;diff=36996</id>
		<title>Префикс-функция</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B5%D1%84%D0%B8%D0%BA%D1%81-%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D1%8F&amp;diff=36996"/>
				<updated>2014-05-14T12:56:22Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition = '''Префикс-функция''' ''(prefix-function)'' от строки(обозначается &amp;lt;tex&amp;gt;\pi(s,i)&amp;lt;/tex&amp;gt;) - длина наибольшего префикса строки &amp;lt;tex&amp;gt;S[1..i]&amp;lt;/tex&amp;gt;, который не совпадает с этой строкой и одновременно является ее суффиксом}}&lt;br /&gt;
&lt;br /&gt;
Префикс-функция строки &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; {{---}} функция &amp;lt;tex&amp;gt;\pi(s, i) = \max\limits_{k = 1..i - 1} \{ 0, k : &amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;s[1..k] = s[i - k + 1..i] \}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Здесь и далее считаем, что символы в строках нумеруются с &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
==Наивный алгоритм==&lt;br /&gt;
Наивный алгоритм вычисляет префикс функцию непосредственно по определению, сравнивая префиксы и суффиксы строк.&lt;br /&gt;
&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
 '''Prefix_function''' (&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;)&lt;br /&gt;
      fill(&amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;, 0)&lt;br /&gt;
      '''for''' i = 1 '''to''' s.length &lt;br /&gt;
          '''for''' k = 1 '''to''' i&lt;br /&gt;
              '''if''' s[1..k] == s[i - k + 1..i])&lt;br /&gt;
                  &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;[i] = k&lt;br /&gt;
      '''return''' &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
Рассмотрим строку abcabcd, для которой значение префикс-функции равно &amp;lt;tex&amp;gt;[0,0,0,1,2,3,0]&amp;lt;/tex&amp;gt;.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Шаг || Строка || Значение функции&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; || a || 0&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; || ab || 0&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt; || abc || 0&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt; || abca || 1&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt; || abcab || 2&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;6&amp;lt;/tex&amp;gt; || abcabc || 3&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;7&amp;lt;/tex&amp;gt; || abcabcd || 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Время работы===&lt;br /&gt;
Всего &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; итераций цикла, на каждой из который происходит сравнение строк за &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;, что дает в итоге &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Эффективный алгоритм==&lt;br /&gt;
Вносятся несколько важных замечаний:&lt;br /&gt;
*Заметим, что &amp;lt;tex&amp;gt;\pi[i + 1] \le \pi[i] + 1&amp;lt;/tex&amp;gt;. Чтобы показать это, рассмотрим суффикс,оканчивающийся на позиции &amp;lt;tex&amp;gt;i + 1&amp;lt;/tex&amp;gt; и имеющий длину &amp;lt;tex&amp;gt;\pi[i + 1]&amp;lt;/tex&amp;gt;, удалив из него последний символ, мы получим суффикс, оканчивающийся на позиции &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; и имеющий длину &amp;lt;tex&amp;gt;\pi[i + 1] - 1&amp;lt;/tex&amp;gt;, следовательно неравенство &amp;lt;tex&amp;gt;\pi[i + 1] &amp;gt; \pi[i] + 1&amp;lt;/tex&amp;gt; неверно.&lt;br /&gt;
*Избавимся от явных сравнений строк. Пусть мы вычислили &amp;lt;tex&amp;gt;\pi[i]&amp;lt;/tex&amp;gt;, тогда, если &amp;lt;tex&amp;gt;s[i + 1] = s[\pi[i]]&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\pi[i + 1] = \pi[i] + 1&amp;lt;/tex&amp;gt;. Если окажется, что &amp;lt;tex&amp;gt;s[i + 1] \ne s[\pi[i]]&amp;lt;/tex&amp;gt;, то нужно попытаться попробовать подстроку меньшей длины. Для этого подберем такое &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;, что &amp;lt;tex&amp;gt;k = \pi(i) - 1&amp;lt;/tex&amp;gt;. Делаем это следующим образом. За исходное &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; необходимо взять &amp;lt;tex&amp;gt;\pi(i - 1)&amp;lt;/tex&amp;gt;, что следует из первого пункта. В случае, когда символы &amp;lt;tex&amp;gt;s[k+1]&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;s[i]&amp;lt;/tex&amp;gt; не совпадают, &amp;lt;tex&amp;gt;\pi(k)&amp;lt;/tex&amp;gt; {{---}} следующее потенциальное наибольшее значение &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;, что видно из рисунка. Последнее утверждение верно, пока &amp;lt;tex&amp;gt;k&amp;gt;0&amp;lt;/tex&amp;gt;, что позволит всегда найти его следующее значение. Если &amp;lt;tex&amp;gt;k=0&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\pi(i)=1&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;s[i] = s[1]&amp;lt;/tex&amp;gt; , иначе &amp;lt;tex&amp;gt;\pi(i)=0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Prfx.jpg‎]]&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
 '''Prefix_function''' (&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;)&lt;br /&gt;
      &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;[1] = 0&lt;br /&gt;
      k = 0&lt;br /&gt;
      '''for''' i = 2 '''to''' s.length&lt;br /&gt;
          k = &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;[i-1]&lt;br /&gt;
          '''while''' k &amp;gt; 0 &amp;amp;&amp;amp; s[i] != s[k + 1] &lt;br /&gt;
              k = &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;[k]&lt;br /&gt;
          '''if''' s[i] == s[k + 1]&lt;br /&gt;
              k++&lt;br /&gt;
          &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;[i] = k&lt;br /&gt;
      '''return''' &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Время работы===&lt;br /&gt;
Время работы алгоритма составит &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для доказательства этого нужно заметить, что итоговое количество итераций цикла &amp;lt;tex&amp;gt;while&amp;lt;/tex&amp;gt; определяет асимптотику алгоритма. Теперь стоит отметить, что &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; увеличивается на каждом шаге не более чем на единицу, значит максимально возможное значение &amp;lt;tex&amp;gt;k = n - 1&amp;lt;/tex&amp;gt;. Поскольку внутри цикла &amp;lt;tex&amp;gt;while&amp;lt;/tex&amp;gt; значение &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; лишь уменьшается, получается, что &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; не может суммарно уменьшиться больше, чем &amp;lt;tex&amp;gt;n-1&amp;lt;/tex&amp;gt; раз. Значит цикл &amp;lt;tex&amp;gt;while&amp;lt;/tex&amp;gt; в итоге выполнится не более &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; раз, что дает итоговую оценку времени алгоритма &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Построение строки по префикс-функции==&lt;br /&gt;
===Постановка задачи=== &lt;br /&gt;
Восстановить строку по префикс-функции за &amp;lt;tex&amp;gt;O(N)&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;s&amp;lt;/tex&amp;gt; будет записан ответ. Пойдем по массиву &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; слева направо.&lt;br /&gt;
&lt;br /&gt;
Пусть мы хотим узнать значение &amp;lt;tex&amp;gt;s[i]&amp;lt;/tex&amp;gt;. Для этого посмотрим на значение &amp;lt;tex&amp;gt;p[i]&amp;lt;/tex&amp;gt;: если &amp;lt;tex&amp;gt;p[i] =0&amp;lt;/tex&amp;gt; тогда в &amp;lt;tex&amp;gt;s[i]&amp;lt;/tex&amp;gt; запишем новый символ, иначе &amp;lt;tex&amp;gt;s[i] = s[p[i]]&amp;lt;/tex&amp;gt;. Обратим внимание, что  &amp;lt;tex&amp;gt;s[p[i]]&amp;lt;/tex&amp;gt; нам уже известно, так как &amp;lt;tex&amp;gt;p[i] &amp;lt; i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Реализация ===&lt;br /&gt;
 '''string''' buildFromPrefix('''int'''[] p):&lt;br /&gt;
   s = &amp;quot;&amp;quot; &lt;br /&gt;
   '''for''' i = 0 '''to''' p.length - 1&lt;br /&gt;
       '''if''' p[i] == 0     &lt;br /&gt;
           s += new character&lt;br /&gt;
       '''else'''&lt;br /&gt;
           s += s[p[i]]&lt;br /&gt;
   '''return''' s&lt;br /&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;s'&amp;lt;/tex&amp;gt; правильная строка, строку &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; построил наш алгоритм, &amp;lt;tex&amp;gt; q &amp;lt;/tex&amp;gt; массив значений префикс-функции для &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Докажем корректность индукцией по длине массива префикс-функции полученной строки. Для начала заметим, что на предыдущие значения массива &amp;lt;tex&amp;gt; q &amp;lt;/tex&amp;gt; прибавление нового символа не влияет, так как при подсчёте префикс-функции на &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;-ой позиции рассматриваются символы на позициях не больше &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;. Поэтому достаточно показать, что очередное значение префикс-функции будет вычислено правильно.&lt;br /&gt;
* База очевидна для строки длины &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* Переход: пусть до &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;-ой позиции мы построили строку, что &amp;lt;tex&amp;gt;p[1..n - 1] = q[1..n - 1]&amp;lt;/tex&amp;gt;. Возможны два случая:&lt;br /&gt;
**  &amp;lt;tex&amp;gt;p[n] = 0&amp;lt;/tex&amp;gt;. Тогда мы добавляем новый символ, поэтому &amp;lt;tex&amp;gt;q[n]&amp;lt;/tex&amp;gt; тоже будет равно &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;. &lt;br /&gt;
** &amp;lt;tex&amp;gt;p[n] &amp;gt; 0&amp;lt;/tex&amp;gt;. По свойствам префикс-функции &amp;lt;tex&amp;gt; s'[p[n]] = s'[n] &amp;lt;/tex&amp;gt; {{---}} суффикс и префикс строки &amp;lt;tex&amp;gt; s' &amp;lt;/tex&amp;gt; длины &amp;lt;tex&amp;gt; p[n] &amp;lt;/tex&amp;gt; продолжаются одним символом, значит, надо на текущую позицию строки &amp;lt;tex&amp;gt; s &amp;lt;/tex&amp;gt; поставить символ &amp;lt;tex&amp;gt; s[p[n]] &amp;lt;/tex&amp;gt;. Если значение префикс-функции увеличивается, значит, текущим символом продолжается префикс длины &amp;lt;tex&amp;gt; p[n - 1] &amp;lt;/tex&amp;gt;, а из свойств следует, что &amp;lt;tex&amp;gt; p[n - 1] \geqslant p[n] - 1 &amp;lt;/tex&amp;gt;. По предположению индукцию значение &amp;lt;tex&amp;gt; q[n - 1] &amp;lt;/tex&amp;gt; будет вычислено верно. А если значение префикс-функции не увеличивается, значит, символ &amp;lt;tex&amp;gt; s[n] &amp;lt;/tex&amp;gt; должен продолжить префикс меньшей длины, а в текущее значение префикс-функции запишется как раз длина нового бордера. Для этого будут использованы значения префикс-функции с меньшими индексами, которые посчитаны верно, опять же по препдположению индукции.&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
* Кормен Т., Лейзерсон Ч., Ривест Р. Алгоритмы: построение и анализ. {{---}} 2-е изд. {{---}} М.: Издательский дом «Вильямс», 2007. {{---}} С. 1296 ISBN 978-5-8459-0857-5&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Поиск подстроки в строке]]&lt;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B5%D1%84%D0%B8%D0%BA%D1%81-%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D1%8F&amp;diff=36995</id>
		<title>Префикс-функция</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B5%D1%84%D0%B8%D0%BA%D1%81-%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D1%8F&amp;diff=36995"/>
				<updated>2014-05-14T12:49:52Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition = '''Префикс-функция''' ''(prefix-function)'' от строки(обозначается &amp;lt;tex&amp;gt;\pi(s,i)&amp;lt;/tex&amp;gt;) - длина наибольшего префикса строки &amp;lt;tex&amp;gt;S[1..i]&amp;lt;/tex&amp;gt;, который не совпадает с этой строкой и одновременно является ее суффиксом}}&lt;br /&gt;
&lt;br /&gt;
Префикс-функция строки &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; {{---}} функция &amp;lt;tex&amp;gt;\pi(s, i) = \max\limits_{k = 1..i - 1} \{ 0, k : &amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;s[1..k] = s[i - k + 1..i] \}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Здесь и далее считаем, что символы в строках нумеруются с &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
==Наивный алгоритм==&lt;br /&gt;
Наивный алгоритм вычисляет префикс функцию непосредственно по определению, сравнивая префиксы и суффиксы строк.&lt;br /&gt;
&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
 '''Prefix_function''' (&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;)&lt;br /&gt;
      fill(&amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;, 0)&lt;br /&gt;
      '''for''' i = 1 '''to''' s.length &lt;br /&gt;
          '''for''' k = 1 '''to''' i&lt;br /&gt;
              '''if''' s[1..k] == s[i - k + 1..i])&lt;br /&gt;
                  &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;[i] = k&lt;br /&gt;
      '''return''' &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
Рассмотрим строку abcabcd, для которой значение префикс-функции равно &amp;lt;tex&amp;gt;[0,0,0,1,2,3,0]&amp;lt;/tex&amp;gt;.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Шаг || Строка || Значение функции&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; || a || 0&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; || ab || 0&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt; || abc || 0&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt; || abca || 1&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt; || abcab || 2&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;6&amp;lt;/tex&amp;gt; || abcabc || 3&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;7&amp;lt;/tex&amp;gt; || abcabcd || 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Время работы===&lt;br /&gt;
Всего &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; итераций цикла, на каждой из который происходит сравнение строк за &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;, что дает в итоге &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Эффективный алгоритм==&lt;br /&gt;
Вносятся несколько важных замечаний:&lt;br /&gt;
*Заметим, что &amp;lt;tex&amp;gt;\pi[i + 1] \le \pi[i] + 1&amp;lt;/tex&amp;gt;. Чтобы показать это, рассмотрим суффикс,оканчивающийся на позиции &amp;lt;tex&amp;gt;i + 1&amp;lt;/tex&amp;gt; и имеющий длину &amp;lt;tex&amp;gt;\pi[i + 1]&amp;lt;/tex&amp;gt;, удалив из него последний символ, мы получим суффикс, оканчивающийся на позиции &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; и имеющий длину &amp;lt;tex&amp;gt;\pi[i + 1] - 1&amp;lt;/tex&amp;gt;, следовательно неравенство &amp;lt;tex&amp;gt;\pi[i + 1] &amp;gt; \pi[i] + 1&amp;lt;/tex&amp;gt; неверно.&lt;br /&gt;
*Избавимся от явных сравнений строк. Пусть мы вычислили &amp;lt;tex&amp;gt;\pi[i]&amp;lt;/tex&amp;gt;, тогда, если &amp;lt;tex&amp;gt;s[i + 1] = s[\pi[i]]&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\pi[i + 1] = \pi[i] + 1&amp;lt;/tex&amp;gt;. Если окажется, что &amp;lt;tex&amp;gt;s[i + 1] \ne s[\pi[i]]&amp;lt;/tex&amp;gt;, то нужно попытаться попробовать подстроку меньшей длины. Для этого подберем такое &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;, что &amp;lt;tex&amp;gt;k = \pi(i) - 1&amp;lt;/tex&amp;gt;. Делаем это следующим образом. За исходное &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; необходимо взять &amp;lt;tex&amp;gt;\pi(i - 1)&amp;lt;/tex&amp;gt;, что следует из первого пункта. В случае, когда символы &amp;lt;tex&amp;gt;s[k+1]&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;s[i]&amp;lt;/tex&amp;gt; не совпадают, &amp;lt;tex&amp;gt;\pi(k)&amp;lt;/tex&amp;gt; {{---}} следующее потенциальное наибольшее значение &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;, что видно из рисунка. Последнее утверждение верно, пока &amp;lt;tex&amp;gt;k&amp;gt;0&amp;lt;/tex&amp;gt;, что позволит всегда найти его следующее значение. Если &amp;lt;tex&amp;gt;k=0&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\pi(i)=1&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;s[i] = s[1]&amp;lt;/tex&amp;gt; , иначе &amp;lt;tex&amp;gt;\pi(i)=0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Prfx.jpg‎]]&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
 '''Prefix_function''' (&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;)&lt;br /&gt;
      &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;[1] = 0&lt;br /&gt;
      k = 0&lt;br /&gt;
      '''for''' (i = 2; i &amp;lt; s.length; i++) {&lt;br /&gt;
          '''while''' (k &amp;gt; 0 &amp;amp;&amp;amp; s[i] != s[k + 1]) {&lt;br /&gt;
              k = &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;[k]&lt;br /&gt;
          }&lt;br /&gt;
          '''if''' (s[i] == s[k + 1]) {&lt;br /&gt;
              k++&lt;br /&gt;
          }&lt;br /&gt;
          &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;[i] = k&lt;br /&gt;
      }&lt;br /&gt;
      '''return''' &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Время работы===&lt;br /&gt;
Время работы алгоритма составит &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для доказательства этого нужно заметить, что итоговое количество итераций цикла &amp;lt;tex&amp;gt;while&amp;lt;/tex&amp;gt; определяет асимптотику алгоритма. Теперь стоит отметить, что &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; увеличивается на каждом шаге не более чем на единицу, значит максимально возможное значение &amp;lt;tex&amp;gt;k = n - 1&amp;lt;/tex&amp;gt;. Поскольку внутри цикла &amp;lt;tex&amp;gt;while&amp;lt;/tex&amp;gt; значение &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; лишь уменьшается, получается, что &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; не может суммарно уменьшиться больше, чем &amp;lt;tex&amp;gt;n-1&amp;lt;/tex&amp;gt; раз. Значит цикл &amp;lt;tex&amp;gt;while&amp;lt;/tex&amp;gt; в итоге выполнится не более &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; раз, что дает итоговую оценку времени алгоритма &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Построение строки по префикс-функции==&lt;br /&gt;
===Постановка задачи=== &lt;br /&gt;
Восстановить строку по префикс-функции за &amp;lt;tex&amp;gt;O(N)&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;s&amp;lt;/tex&amp;gt; будет записан ответ. Пойдем по массиву &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; слева направо.&lt;br /&gt;
&lt;br /&gt;
Пусть мы хотим узнать значение &amp;lt;tex&amp;gt;s[i]&amp;lt;/tex&amp;gt;. Для этого посмотрим на значение &amp;lt;tex&amp;gt;p[i]&amp;lt;/tex&amp;gt;: если &amp;lt;tex&amp;gt;p[i] =0&amp;lt;/tex&amp;gt; тогда в &amp;lt;tex&amp;gt;s[i]&amp;lt;/tex&amp;gt; запишем новый символ, иначе &amp;lt;tex&amp;gt;s[i] = s[p[i]]&amp;lt;/tex&amp;gt;. Обратим внимание, что  &amp;lt;tex&amp;gt;s[p[i]]&amp;lt;/tex&amp;gt; нам уже известно, так как &amp;lt;tex&amp;gt;p[i] &amp;lt; i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Реализация ===&lt;br /&gt;
 '''string''' buildFromPrefix('''int'''[] p):&lt;br /&gt;
   s = &amp;quot;&amp;quot; &lt;br /&gt;
   '''for''' i = 0 '''to''' p.length - 1&lt;br /&gt;
       '''if''' p[i] == 0     &lt;br /&gt;
           s += new character&lt;br /&gt;
       '''else'''&lt;br /&gt;
           s += s[p[i]]&lt;br /&gt;
   '''return''' s&lt;br /&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;s'&amp;lt;/tex&amp;gt; правильная строка, строку &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; построил наш алгоритм, &amp;lt;tex&amp;gt; q &amp;lt;/tex&amp;gt; массив значений префикс-функции для &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Докажем корректность индукцией по длине массива префикс-функции полученной строки. Для начала заметим, что на предыдущие значения массива &amp;lt;tex&amp;gt; q &amp;lt;/tex&amp;gt; прибавление нового символа не влияет, так как при подсчёте префикс-функции на &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;-ой позиции рассматриваются символы на позициях не больше &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;. Поэтому достаточно показать, что очередное значение префикс-функции будет вычислено правильно.&lt;br /&gt;
* База очевидна для строки длины &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* Переход: пусть до &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;-ой позиции мы построили строку, что &amp;lt;tex&amp;gt;p[1..n - 1] = q[1..n - 1]&amp;lt;/tex&amp;gt;. Возможны два случая:&lt;br /&gt;
**  &amp;lt;tex&amp;gt;p[n] = 0&amp;lt;/tex&amp;gt;. Тогда мы добавляем новый символ, поэтому &amp;lt;tex&amp;gt;q[n]&amp;lt;/tex&amp;gt; тоже будет равно &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;. &lt;br /&gt;
** &amp;lt;tex&amp;gt;p[n] &amp;gt; 0&amp;lt;/tex&amp;gt;. По свойствам префикс-функции &amp;lt;tex&amp;gt; s'[p[n]] = s'[n] &amp;lt;/tex&amp;gt; {{---}} суффикс и префикс строки &amp;lt;tex&amp;gt; s' &amp;lt;/tex&amp;gt; длины &amp;lt;tex&amp;gt; p[n] &amp;lt;/tex&amp;gt; продолжаются одним символом, значит, надо на текущую позицию строки &amp;lt;tex&amp;gt; s &amp;lt;/tex&amp;gt; поставить символ &amp;lt;tex&amp;gt; s[p[n]] &amp;lt;/tex&amp;gt;. Если значение префикс-функции увеличивается, значит, текущим символом продолжается префикс длины &amp;lt;tex&amp;gt; p[n - 1] &amp;lt;/tex&amp;gt;, а из свойств следует, что &amp;lt;tex&amp;gt; p[n - 1] \geqslant p[n] - 1 &amp;lt;/tex&amp;gt;. По предположению индукцию значение &amp;lt;tex&amp;gt; q[n - 1] &amp;lt;/tex&amp;gt; будет вычислено верно. А если значение префикс-функции не увеличивается, значит, символ &amp;lt;tex&amp;gt; s[n] &amp;lt;/tex&amp;gt; должен продолжить префикс меньшей длины, а в текущее значение префикс-функции запишется как раз длина нового бордера. Для этого будут использованы значения префикс-функции с меньшими индексами, которые посчитаны верно, опять же по препдположению индукции.&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
* Кормен Т., Лейзерсон Ч., Ривест Р. Алгоритмы: построение и анализ. {{---}} 2-е изд. {{---}} М.: Издательский дом «Вильямс», 2007. {{---}} С. 1296 ISBN 978-5-8459-0857-5&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Поиск подстроки в строке]]&lt;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B5%D1%84%D0%B8%D0%BA%D1%81-%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D1%8F&amp;diff=36980</id>
		<title>Префикс-функция</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B5%D1%84%D0%B8%D0%BA%D1%81-%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D1%8F&amp;diff=36980"/>
				<updated>2014-05-13T20:19:09Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition = '''Префикс-функция''' ''(prefix-function)'' от строки(обозначается &amp;lt;tex&amp;gt;\pi(s,i)&amp;lt;/tex&amp;gt;) - длина наибольшего префикса строки &amp;lt;tex&amp;gt;S[1..i]&amp;lt;/tex&amp;gt;, который не совпадает с этой строкой и одновременно является ее суффиксом}}&lt;br /&gt;
&lt;br /&gt;
Префикс-функция строки &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; {{---}} функция &amp;lt;tex&amp;gt;\pi(s, i) = \max\limits_{k = 1..i - 1} \{ 0, k : &amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;s[1..k] = s[i - k + 1..i] \}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Здесь и далее считаем, что символы в строках нумеруются с &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
==Наивный алгоритм==&lt;br /&gt;
Наивный алгоритм вычисляет префикс функцию непосредственно по определению, сравнивая префиксы и суффиксы строк.&lt;br /&gt;
&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
 '''Prefix_function''' (&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;)&lt;br /&gt;
      fill(&amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;, 0)&lt;br /&gt;
      '''for''' (i = 1; i &amp;lt; s.length; i++) {&lt;br /&gt;
          '''for''' (k = 1; k &amp;lt; i; k++) {&lt;br /&gt;
              '''if''' (s[1..k] == s[i - k + 1..i]) {&lt;br /&gt;
                  &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;[i] = k&lt;br /&gt;
              }&lt;br /&gt;
          }&lt;br /&gt;
      }&lt;br /&gt;
      '''return''' &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
Рассмотрим строку abcabcd, для которой значение префикс-функции равно &amp;lt;tex&amp;gt;[0,0,0,1,2,3,0]&amp;lt;/tex&amp;gt;.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Шаг || Строка || Значение функции&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; || a || 0&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; || ab || 0&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt; || abc || 0&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt; || abca || 1&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt; || abcab || 2&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;6&amp;lt;/tex&amp;gt; || abcabc || 3&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;7&amp;lt;/tex&amp;gt; || abcabcd || 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Время работы===&lt;br /&gt;
Всего &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; итераций цикла, на каждой из который происходит сравнение строк за &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;, что дает в итоге &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Эффективный алгоритм==&lt;br /&gt;
Вносятся несколько важных замечаний:&lt;br /&gt;
*Заметим, что &amp;lt;tex&amp;gt;\pi[i + 1] \le \pi[i] + 1&amp;lt;/tex&amp;gt;. Чтобы показать это, рассмотрим суффикс,оканчивающийся на позиции &amp;lt;tex&amp;gt;i + 1&amp;lt;/tex&amp;gt; и имеющий длину &amp;lt;tex&amp;gt;\pi[i + 1]&amp;lt;/tex&amp;gt;, удалив из него последний символ, мы получим суффикс, оканчивающийся на позиции &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; и имеющий длину &amp;lt;tex&amp;gt;\pi[i + 1] - 1&amp;lt;/tex&amp;gt;, следовательно неравенство &amp;lt;tex&amp;gt;\pi[i + 1] &amp;gt; \pi[i] + 1&amp;lt;/tex&amp;gt; неверно.&lt;br /&gt;
*Избавимся от явных сравнений строк. Пусть мы вычислили &amp;lt;tex&amp;gt;\pi[i]&amp;lt;/tex&amp;gt;, тогда, если &amp;lt;tex&amp;gt;s[i + 1] = s[\pi[i]]&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\pi[i + 1] = \pi[i] + 1&amp;lt;/tex&amp;gt;. Если окажется, что &amp;lt;tex&amp;gt;s[i + 1] \ne s[\pi[i]]&amp;lt;/tex&amp;gt;, то нужно попытаться попробовать подстроку меньшей длины. Для этого подберем такое &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;, что &amp;lt;tex&amp;gt;k = \pi(i) - 1&amp;lt;/tex&amp;gt;. Делаем это следующим образом. За исходное &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; необходимо взять &amp;lt;tex&amp;gt;\pi(i - 1)&amp;lt;/tex&amp;gt;, что следует из первого пункта. В случае, когда символы &amp;lt;tex&amp;gt;s[k+1]&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;s[i]&amp;lt;/tex&amp;gt; не совпадают, &amp;lt;tex&amp;gt;\pi(k)&amp;lt;/tex&amp;gt; {{---}} следующее потенциальное наибольшее значение &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;, что видно из рисунка. Последнее утверждение верно, пока &amp;lt;tex&amp;gt;k&amp;gt;0&amp;lt;/tex&amp;gt;, что позволит всегда найти его следующее значение. Если &amp;lt;tex&amp;gt;k=0&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\pi(i)=1&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;s[i] = s[1]&amp;lt;/tex&amp;gt; , иначе &amp;lt;tex&amp;gt;\pi(i)=0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Prefix2.jpg‎]]&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
 '''Prefix_function''' (&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;)&lt;br /&gt;
      &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;[1] = 0&lt;br /&gt;
      k = 0&lt;br /&gt;
      '''for''' (i = 2; i &amp;lt; s.length; i++) {&lt;br /&gt;
          '''while''' (k &amp;gt; 0 &amp;amp;&amp;amp; s[i] != s[k + 1]) {&lt;br /&gt;
              k = &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;[k]&lt;br /&gt;
          }&lt;br /&gt;
          '''if''' (s[i] == s[k + 1]) {&lt;br /&gt;
              k++&lt;br /&gt;
          }&lt;br /&gt;
          &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;[i] = k&lt;br /&gt;
      }&lt;br /&gt;
      '''return''' &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Время работы===&lt;br /&gt;
Время работы алгоритма составит &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для доказательства этого нужно заметить, что итоговое количество итераций цикла &amp;lt;tex&amp;gt;while&amp;lt;/tex&amp;gt; определяет асимптотику алгоритма. Теперь стоит отметить, что &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; увеличивается на каждом шаге не более чем на единицу, значит максимально возможное значение &amp;lt;tex&amp;gt;k = n - 1&amp;lt;/tex&amp;gt;. Поскольку внутри цикла &amp;lt;tex&amp;gt;while&amp;lt;/tex&amp;gt; значение &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; лишь уменьшается, получается, что &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; не может суммарно уменьшиться больше, чем &amp;lt;tex&amp;gt;n-1&amp;lt;/tex&amp;gt; раз. Значит цикл &amp;lt;tex&amp;gt;while&amp;lt;/tex&amp;gt; в итоге выполнится не более &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; раз, что дает итоговую оценку времени алгоритма &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Построение строки по префикс-функции==&lt;br /&gt;
===Постановка задачи=== &lt;br /&gt;
Восстановить строку по префикс-функции за &amp;lt;tex&amp;gt;O(N)&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;s&amp;lt;/tex&amp;gt; будет записан ответ. Пойдем по массиву &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; слева направо.&lt;br /&gt;
&lt;br /&gt;
Пусть мы хотим узнать значение &amp;lt;tex&amp;gt;s[i]&amp;lt;/tex&amp;gt;. Для этого посмотрим на значение &amp;lt;tex&amp;gt;p[i]&amp;lt;/tex&amp;gt;: если &amp;lt;tex&amp;gt;p[i] =0&amp;lt;/tex&amp;gt; тогда в &amp;lt;tex&amp;gt;s[i]&amp;lt;/tex&amp;gt; запишем новый символ, иначе &amp;lt;tex&amp;gt;s[i] = s[p[i]]&amp;lt;/tex&amp;gt;. Обратим внимание, что  &amp;lt;tex&amp;gt;s[p[i]]&amp;lt;/tex&amp;gt; нам уже известно, так как &amp;lt;tex&amp;gt;p[i] &amp;lt; i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Реализация ===&lt;br /&gt;
 '''string''' buildFromPrefix('''int'''[] p):&lt;br /&gt;
   s = &amp;quot;&amp;quot; &lt;br /&gt;
   '''for''' i = 0 '''to''' p.length - 1&lt;br /&gt;
       '''if''' p[i] == 0     &lt;br /&gt;
           s += new character&lt;br /&gt;
       '''else'''&lt;br /&gt;
           s += s[p[i]]&lt;br /&gt;
   '''return''' s&lt;br /&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;s'&amp;lt;/tex&amp;gt; правильная строка, строку &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; построил наш алгоритм, &amp;lt;tex&amp;gt; q &amp;lt;/tex&amp;gt; массив значений префикс-функции для &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Докажем корректность индукцией по длине массива префикс-функции полученной строки. Для начала заметим, что на предыдущие значения массива &amp;lt;tex&amp;gt; q &amp;lt;/tex&amp;gt; прибавление нового символа не влияет, так как при подсчёте префикс-функции на &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;-ой позиции рассматриваются символы на позициях не больше &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;. Поэтому достаточно показать, что очередное значение префикс-функции будет вычислено правильно.&lt;br /&gt;
* База очевидна для строки длины &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* Переход: пусть до &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;-ой позиции мы построили строку, что &amp;lt;tex&amp;gt;p[1..n - 1] = q[1..n - 1]&amp;lt;/tex&amp;gt;. Возможны два случая:&lt;br /&gt;
**  &amp;lt;tex&amp;gt;p[n] = 0&amp;lt;/tex&amp;gt;. Тогда мы добавляем новый символ, поэтому &amp;lt;tex&amp;gt;q[n]&amp;lt;/tex&amp;gt; тоже будет равно &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;. &lt;br /&gt;
** &amp;lt;tex&amp;gt;p[n] &amp;gt; 0&amp;lt;/tex&amp;gt;. По свойствам префикс-функции &amp;lt;tex&amp;gt; s'[p[n]] = s'[n] &amp;lt;/tex&amp;gt; {{---}} суффикс и префикс строки &amp;lt;tex&amp;gt; s' &amp;lt;/tex&amp;gt; длины &amp;lt;tex&amp;gt; p[n] &amp;lt;/tex&amp;gt; продолжаются одним символом, значит, надо на текущую позицию строки &amp;lt;tex&amp;gt; s &amp;lt;/tex&amp;gt; поставить символ &amp;lt;tex&amp;gt; s[p[n]] &amp;lt;/tex&amp;gt;. Если значение префикс-функции увеличивается, значит, текущим символом продолжается префикс длины &amp;lt;tex&amp;gt; p[n - 1] &amp;lt;/tex&amp;gt;, а из свойств следует, что &amp;lt;tex&amp;gt; p[n - 1] \geqslant p[n] - 1 &amp;lt;/tex&amp;gt;. По предположению индукцию значение &amp;lt;tex&amp;gt; q[n - 1] &amp;lt;/tex&amp;gt; будет вычислено верно. А если значение префикс-функции не увеличивается, значит, символ &amp;lt;tex&amp;gt; s[n] &amp;lt;/tex&amp;gt; должен продолжить префикс меньшей длины, а в текущее значение префикс-функции запишется как раз длина нового бордера. Для этого будут использованы значения префикс-функции с меньшими индексами, которые посчитаны верно, опять же по препдположению индукции.&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
* Кормен Т., Лейзерсон Ч., Ривест Р. Алгоритмы: построение и анализ. {{---}} 2-е изд. {{---}} М.: Издательский дом «Вильямс», 2007. {{---}} С. 1296 ISBN 978-5-8459-0857-5&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Поиск подстроки в строке]]&lt;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B5%D1%84%D0%B8%D0%BA%D1%81-%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D1%8F&amp;diff=36979</id>
		<title>Префикс-функция</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B5%D1%84%D0%B8%D0%BA%D1%81-%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D1%8F&amp;diff=36979"/>
				<updated>2014-05-13T20:18:18Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition = '''Префикс-функция''' ''(prefix-function)'' от строки(обозначается &amp;lt;tex&amp;gt;\pi(s,i)&amp;lt;/tex&amp;gt;) - длина наибольшего префикса строки &amp;lt;tex&amp;gt;S[1..i]&amp;lt;/tex&amp;gt;, который не совпадает с этой строкой и одновременно является ее суффиксом}}&lt;br /&gt;
&lt;br /&gt;
Префикс-функция строки &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; {{---}} функция &amp;lt;tex&amp;gt;\pi(s, i) = \max\limits_{k = 1..i - 1} \{ 0, k : &amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;s[1..k] = s[i - k + 1..i] \}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Здесь и далее считаем, что символы в строках нумеруются с &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
==Наивный алгоритм==&lt;br /&gt;
Наивный алгоритм вычисляет префикс функцию непосредственно по определению, сравнивая префиксы и суффиксы строк.&lt;br /&gt;
&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
 '''Prefix_function''' (&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;)&lt;br /&gt;
      &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt; = [0,..,0]&lt;br /&gt;
      '''for''' (i = 1; i &amp;lt; s.length; i++) {&lt;br /&gt;
          '''for''' (k = 1; k &amp;lt; i; k++) {&lt;br /&gt;
              '''if''' (s[1..k] == s[i - k + 1..i]) {&lt;br /&gt;
                  &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;[i] = k&lt;br /&gt;
              }&lt;br /&gt;
          }&lt;br /&gt;
      }&lt;br /&gt;
      '''return''' &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
Рассмотрим строку abcabcd, для которой значение префикс-функции равно &amp;lt;tex&amp;gt;[0,0,0,1,2,3,0]&amp;lt;/tex&amp;gt;.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Шаг || Строка || Значение функции&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; || a || 0&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; || ab || 0&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt; || abc || 0&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt; || abca || 1&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt; || abcab || 2&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;6&amp;lt;/tex&amp;gt; || abcabc || 3&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;7&amp;lt;/tex&amp;gt; || abcabcd || 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Время работы===&lt;br /&gt;
Всего &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; итераций цикла, на каждой из который происходит сравнение строк за &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;, что дает в итоге &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Эффективный алгоритм==&lt;br /&gt;
Вносятся несколько важных замечаний:&lt;br /&gt;
*Заметим, что &amp;lt;tex&amp;gt;\pi[i + 1] \le \pi[i] + 1&amp;lt;/tex&amp;gt;. Чтобы показать это, рассмотрим суффикс,оканчивающийся на позиции &amp;lt;tex&amp;gt;i + 1&amp;lt;/tex&amp;gt; и имеющий длину &amp;lt;tex&amp;gt;\pi[i + 1]&amp;lt;/tex&amp;gt;, удалив из него последний символ, мы получим суффикс, оканчивающийся на позиции &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; и имеющий длину &amp;lt;tex&amp;gt;\pi[i + 1] - 1&amp;lt;/tex&amp;gt;, следовательно неравенство &amp;lt;tex&amp;gt;\pi[i + 1] &amp;gt; \pi[i] + 1&amp;lt;/tex&amp;gt; неверно.&lt;br /&gt;
*Избавимся от явных сравнений строк. Пусть мы вычислили &amp;lt;tex&amp;gt;\pi[i]&amp;lt;/tex&amp;gt;, тогда, если &amp;lt;tex&amp;gt;s[i + 1] = s[\pi[i]]&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\pi[i + 1] = \pi[i] + 1&amp;lt;/tex&amp;gt;. Если окажется, что &amp;lt;tex&amp;gt;s[i + 1] \ne s[\pi[i]]&amp;lt;/tex&amp;gt;, то нужно попытаться попробовать подстроку меньшей длины. Для этого подберем такое &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;, что &amp;lt;tex&amp;gt;k = \pi(i) - 1&amp;lt;/tex&amp;gt;. Делаем это следующим образом. За исходное &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; необходимо взять &amp;lt;tex&amp;gt;\pi(i - 1)&amp;lt;/tex&amp;gt;, что следует из первого пункта. В случае, когда символы &amp;lt;tex&amp;gt;s[k+1]&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;s[i]&amp;lt;/tex&amp;gt; не совпадают, &amp;lt;tex&amp;gt;\pi(k)&amp;lt;/tex&amp;gt; {{---}} следующее потенциальное наибольшее значение &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;, что видно из рисунка. Последнее утверждение верно, пока &amp;lt;tex&amp;gt;k&amp;gt;0&amp;lt;/tex&amp;gt;, что позволит всегда найти его следующее значение. Если &amp;lt;tex&amp;gt;k=0&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\pi(i)=1&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;s[i] = s[1]&amp;lt;/tex&amp;gt; , иначе &amp;lt;tex&amp;gt;\pi(i)=0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Prefix2.jpg‎]]&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
 '''Prefix_function''' (&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;)&lt;br /&gt;
      &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;[1] = 0&lt;br /&gt;
      k = 0&lt;br /&gt;
      '''for''' (i = 2; i &amp;lt; s.length; i++) {&lt;br /&gt;
          '''while''' (k &amp;gt; 0 &amp;amp;&amp;amp; s[i] != s[k + 1]) {&lt;br /&gt;
              k = &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;[k]&lt;br /&gt;
          }&lt;br /&gt;
          '''if''' (s[i] == s[k + 1]) {&lt;br /&gt;
              k++&lt;br /&gt;
          }&lt;br /&gt;
          &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;[i] = k&lt;br /&gt;
      }&lt;br /&gt;
      '''return''' &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Время работы===&lt;br /&gt;
Время работы алгоритма составит &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для доказательства этого нужно заметить, что итоговое количество итераций цикла &amp;lt;tex&amp;gt;while&amp;lt;/tex&amp;gt; определяет асимптотику алгоритма. Теперь стоит отметить, что &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; увеличивается на каждом шаге не более чем на единицу, значит максимально возможное значение &amp;lt;tex&amp;gt;k = n - 1&amp;lt;/tex&amp;gt;. Поскольку внутри цикла &amp;lt;tex&amp;gt;while&amp;lt;/tex&amp;gt; значение &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; лишь уменьшается, получается, что &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; не может суммарно уменьшиться больше, чем &amp;lt;tex&amp;gt;n-1&amp;lt;/tex&amp;gt; раз. Значит цикл &amp;lt;tex&amp;gt;while&amp;lt;/tex&amp;gt; в итоге выполнится не более &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; раз, что дает итоговую оценку времени алгоритма &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Построение строки по префикс-функции==&lt;br /&gt;
===Постановка задачи=== &lt;br /&gt;
Восстановить строку по префикс-функции за &amp;lt;tex&amp;gt;O(N)&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;s&amp;lt;/tex&amp;gt; будет записан ответ. Пойдем по массиву &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; слева направо.&lt;br /&gt;
&lt;br /&gt;
Пусть мы хотим узнать значение &amp;lt;tex&amp;gt;s[i]&amp;lt;/tex&amp;gt;. Для этого посмотрим на значение &amp;lt;tex&amp;gt;p[i]&amp;lt;/tex&amp;gt;: если &amp;lt;tex&amp;gt;p[i] =0&amp;lt;/tex&amp;gt; тогда в &amp;lt;tex&amp;gt;s[i]&amp;lt;/tex&amp;gt; запишем новый символ, иначе &amp;lt;tex&amp;gt;s[i] = s[p[i]]&amp;lt;/tex&amp;gt;. Обратим внимание, что  &amp;lt;tex&amp;gt;s[p[i]]&amp;lt;/tex&amp;gt; нам уже известно, так как &amp;lt;tex&amp;gt;p[i] &amp;lt; i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Реализация ===&lt;br /&gt;
 '''string''' buildFromPrefix('''int'''[] p):&lt;br /&gt;
   s = &amp;quot;&amp;quot; &lt;br /&gt;
   '''for''' i = 0 '''to''' p.length - 1&lt;br /&gt;
       '''if''' p[i] == 0     &lt;br /&gt;
           s += new character&lt;br /&gt;
       '''else'''&lt;br /&gt;
           s += s[p[i]]&lt;br /&gt;
   '''return''' s&lt;br /&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;s'&amp;lt;/tex&amp;gt; правильная строка, строку &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; построил наш алгоритм, &amp;lt;tex&amp;gt; q &amp;lt;/tex&amp;gt; массив значений префикс-функции для &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Докажем корректность индукцией по длине массива префикс-функции полученной строки. Для начала заметим, что на предыдущие значения массива &amp;lt;tex&amp;gt; q &amp;lt;/tex&amp;gt; прибавление нового символа не влияет, так как при подсчёте префикс-функции на &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;-ой позиции рассматриваются символы на позициях не больше &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;. Поэтому достаточно показать, что очередное значение префикс-функции будет вычислено правильно.&lt;br /&gt;
* База очевидна для строки длины &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* Переход: пусть до &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;-ой позиции мы построили строку, что &amp;lt;tex&amp;gt;p[1..n - 1] = q[1..n - 1]&amp;lt;/tex&amp;gt;. Возможны два случая:&lt;br /&gt;
**  &amp;lt;tex&amp;gt;p[n] = 0&amp;lt;/tex&amp;gt;. Тогда мы добавляем новый символ, поэтому &amp;lt;tex&amp;gt;q[n]&amp;lt;/tex&amp;gt; тоже будет равно &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;. &lt;br /&gt;
** &amp;lt;tex&amp;gt;p[n] &amp;gt; 0&amp;lt;/tex&amp;gt;. По свойствам префикс-функции &amp;lt;tex&amp;gt; s'[p[n]] = s'[n] &amp;lt;/tex&amp;gt; {{---}} суффикс и префикс строки &amp;lt;tex&amp;gt; s' &amp;lt;/tex&amp;gt; длины &amp;lt;tex&amp;gt; p[n] &amp;lt;/tex&amp;gt; продолжаются одним символом, значит, надо на текущую позицию строки &amp;lt;tex&amp;gt; s &amp;lt;/tex&amp;gt; поставить символ &amp;lt;tex&amp;gt; s[p[n]] &amp;lt;/tex&amp;gt;. Если значение префикс-функции увеличивается, значит, текущим символом продолжается префикс длины &amp;lt;tex&amp;gt; p[n - 1] &amp;lt;/tex&amp;gt;, а из свойств следует, что &amp;lt;tex&amp;gt; p[n - 1] \geqslant p[n] - 1 &amp;lt;/tex&amp;gt;. По предположению индукцию значение &amp;lt;tex&amp;gt; q[n - 1] &amp;lt;/tex&amp;gt; будет вычислено верно. А если значение префикс-функции не увеличивается, значит, символ &amp;lt;tex&amp;gt; s[n] &amp;lt;/tex&amp;gt; должен продолжить префикс меньшей длины, а в текущее значение префикс-функции запишется как раз длина нового бордера. Для этого будут использованы значения префикс-функции с меньшими индексами, которые посчитаны верно, опять же по препдположению индукции.&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
* Кормен Т., Лейзерсон Ч., Ривест Р. Алгоритмы: построение и анализ. {{---}} 2-е изд. {{---}} М.: Издательский дом «Вильямс», 2007. {{---}} С. 1296 ISBN 978-5-8459-0857-5&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Поиск подстроки в строке]]&lt;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B5%D1%84%D0%B8%D0%BA%D1%81-%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D1%8F&amp;diff=36977</id>
		<title>Префикс-функция</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B5%D1%84%D0%B8%D0%BA%D1%81-%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D1%8F&amp;diff=36977"/>
				<updated>2014-05-13T20:16:50Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition = '''Префикс-функция''' ''(prefix-function)'' от строки(обозначается &amp;lt;tex&amp;gt;\pi(s,i)&amp;lt;/tex&amp;gt;) - длина наибольшего префикса строки &amp;lt;tex&amp;gt;S[1..i]&amp;lt;/tex&amp;gt;, который не совпадает с этой строкой и одновременно является ее суффиксом}}&lt;br /&gt;
&lt;br /&gt;
Префикс-функция строки &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; {{---}} функция &amp;lt;tex&amp;gt;\pi(s, i) = \max\limits_{k = 1..i - 1} \{ 0, k : &amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;s[1..k] = s[i - k + 1..i] \}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Здесь и далее считаем, что символы в строках нумеруются с &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
==Наивный алгоритм==&lt;br /&gt;
Наивный алгоритм вычисляет префикс функцию непосредственно по определению, сравнивая префиксы и суффиксы строк.&lt;br /&gt;
&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
 '''Prefix_function''' (&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;)&lt;br /&gt;
      &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt; = [0,..,0]&lt;br /&gt;
      '''for''' i = 1 '''to''' n&lt;br /&gt;
          '''for''' k = 1 '''to''' i - 1&lt;br /&gt;
              '''if''' s[1..k] == s[i - k + 1..i]&lt;br /&gt;
                  &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;[i] = k&lt;br /&gt;
      '''return''' &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
Рассмотрим строку abcabcd, для которой значение префикс-функции равно &amp;lt;tex&amp;gt;[0,0,0,1,2,3,0]&amp;lt;/tex&amp;gt;.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Шаг || Строка || Значение функции&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; || a || 0&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; || ab || 0&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt; || abc || 0&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt; || abca || 1&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt; || abcab || 2&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;6&amp;lt;/tex&amp;gt; || abcabc || 3&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;7&amp;lt;/tex&amp;gt; || abcabcd || 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Время работы===&lt;br /&gt;
Всего &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; итераций цикла, на каждой из который происходит сравнение строк за &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;, что дает в итоге &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Эффективный алгоритм==&lt;br /&gt;
Вносятся несколько важных замечаний:&lt;br /&gt;
*Заметим, что &amp;lt;tex&amp;gt;\pi[i + 1] \le \pi[i] + 1&amp;lt;/tex&amp;gt;. Чтобы показать это, рассмотрим суффикс,оканчивающийся на позиции &amp;lt;tex&amp;gt;i + 1&amp;lt;/tex&amp;gt; и имеющий длину &amp;lt;tex&amp;gt;\pi[i + 1]&amp;lt;/tex&amp;gt;, удалив из него последний символ, мы получим суффикс, оканчивающийся на позиции &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; и имеющий длину &amp;lt;tex&amp;gt;\pi[i + 1] - 1&amp;lt;/tex&amp;gt;, следовательно неравенство &amp;lt;tex&amp;gt;\pi[i + 1] &amp;gt; \pi[i] + 1&amp;lt;/tex&amp;gt; неверно.&lt;br /&gt;
*Избавимся от явных сравнений строк. Пусть мы вычислили &amp;lt;tex&amp;gt;\pi[i]&amp;lt;/tex&amp;gt;, тогда, если &amp;lt;tex&amp;gt;s[i + 1] = s[\pi[i]]&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\pi[i + 1] = \pi[i] + 1&amp;lt;/tex&amp;gt;. Если окажется, что &amp;lt;tex&amp;gt;s[i + 1] \ne s[\pi[i]]&amp;lt;/tex&amp;gt;, то нужно попытаться попробовать подстроку меньшей длины. Для этого подберем такое &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;, что &amp;lt;tex&amp;gt;k = \pi(i) - 1&amp;lt;/tex&amp;gt;. Делаем это следующим образом. За исходное &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; необходимо взять &amp;lt;tex&amp;gt;\pi(i - 1)&amp;lt;/tex&amp;gt;, что следует из первого пункта. В случае, когда символы &amp;lt;tex&amp;gt;s[k+1]&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;s[i]&amp;lt;/tex&amp;gt; не совпадают, &amp;lt;tex&amp;gt;\pi(k)&amp;lt;/tex&amp;gt; {{---}} следующее потенциальное наибольшее значение &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;, что видно из рисунка. Последнее утверждение верно, пока &amp;lt;tex&amp;gt;k&amp;gt;0&amp;lt;/tex&amp;gt;, что позволит всегда найти его следующее значение. Если &amp;lt;tex&amp;gt;k=0&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\pi(i)=1&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;s[i] = s[1]&amp;lt;/tex&amp;gt; , иначе &amp;lt;tex&amp;gt;\pi(i)=0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Prefix2.jpg‎]]&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
 '''Prefix_function''' (&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;)&lt;br /&gt;
      &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;[1] = 0&lt;br /&gt;
      k = 0&lt;br /&gt;
      '''for''' (i = 2; i &amp;lt; s.length; i++) {&lt;br /&gt;
          '''while''' (k &amp;gt; 0 &amp;amp;&amp;amp; s[i] != s[k + 1]) {&lt;br /&gt;
              k = &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;[k]&lt;br /&gt;
          }&lt;br /&gt;
          '''if''' (s[i] == s[k + 1]) {&lt;br /&gt;
              k++&lt;br /&gt;
          }&lt;br /&gt;
          &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;[i] = k&lt;br /&gt;
      }&lt;br /&gt;
      '''return''' &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Время работы===&lt;br /&gt;
Время работы алгоритма составит &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для доказательства этого нужно заметить, что итоговое количество итераций цикла &amp;lt;tex&amp;gt;while&amp;lt;/tex&amp;gt; определяет асимптотику алгоритма. Теперь стоит отметить, что &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; увеличивается на каждом шаге не более чем на единицу, значит максимально возможное значение &amp;lt;tex&amp;gt;k = n - 1&amp;lt;/tex&amp;gt;. Поскольку внутри цикла &amp;lt;tex&amp;gt;while&amp;lt;/tex&amp;gt; значение &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; лишь уменьшается, получается, что &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; не может суммарно уменьшиться больше, чем &amp;lt;tex&amp;gt;n-1&amp;lt;/tex&amp;gt; раз. Значит цикл &amp;lt;tex&amp;gt;while&amp;lt;/tex&amp;gt; в итоге выполнится не более &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; раз, что дает итоговую оценку времени алгоритма &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Построение строки по префикс-функции==&lt;br /&gt;
===Постановка задачи=== &lt;br /&gt;
Восстановить строку по префикс-функции за &amp;lt;tex&amp;gt;O(N)&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;s&amp;lt;/tex&amp;gt; будет записан ответ. Пойдем по массиву &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; слева направо.&lt;br /&gt;
&lt;br /&gt;
Пусть мы хотим узнать значение &amp;lt;tex&amp;gt;s[i]&amp;lt;/tex&amp;gt;. Для этого посмотрим на значение &amp;lt;tex&amp;gt;p[i]&amp;lt;/tex&amp;gt;: если &amp;lt;tex&amp;gt;p[i] =0&amp;lt;/tex&amp;gt; тогда в &amp;lt;tex&amp;gt;s[i]&amp;lt;/tex&amp;gt; запишем новый символ, иначе &amp;lt;tex&amp;gt;s[i] = s[p[i]]&amp;lt;/tex&amp;gt;. Обратим внимание, что  &amp;lt;tex&amp;gt;s[p[i]]&amp;lt;/tex&amp;gt; нам уже известно, так как &amp;lt;tex&amp;gt;p[i] &amp;lt; i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Реализация ===&lt;br /&gt;
 '''string''' buildFromPrefix('''int'''[] p):&lt;br /&gt;
   s = &amp;quot;&amp;quot; &lt;br /&gt;
   '''for''' i = 0 '''to''' p.length - 1&lt;br /&gt;
       '''if''' p[i] == 0     &lt;br /&gt;
           s += new character&lt;br /&gt;
       '''else'''&lt;br /&gt;
           s += s[p[i]]&lt;br /&gt;
   '''return''' s&lt;br /&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;s'&amp;lt;/tex&amp;gt; правильная строка, строку &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; построил наш алгоритм, &amp;lt;tex&amp;gt; q &amp;lt;/tex&amp;gt; массив значений префикс-функции для &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Докажем корректность индукцией по длине массива префикс-функции полученной строки. Для начала заметим, что на предыдущие значения массива &amp;lt;tex&amp;gt; q &amp;lt;/tex&amp;gt; прибавление нового символа не влияет, так как при подсчёте префикс-функции на &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;-ой позиции рассматриваются символы на позициях не больше &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;. Поэтому достаточно показать, что очередное значение префикс-функции будет вычислено правильно.&lt;br /&gt;
* База очевидна для строки длины &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* Переход: пусть до &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;-ой позиции мы построили строку, что &amp;lt;tex&amp;gt;p[1..n - 1] = q[1..n - 1]&amp;lt;/tex&amp;gt;. Возможны два случая:&lt;br /&gt;
**  &amp;lt;tex&amp;gt;p[n] = 0&amp;lt;/tex&amp;gt;. Тогда мы добавляем новый символ, поэтому &amp;lt;tex&amp;gt;q[n]&amp;lt;/tex&amp;gt; тоже будет равно &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;. &lt;br /&gt;
** &amp;lt;tex&amp;gt;p[n] &amp;gt; 0&amp;lt;/tex&amp;gt;. По свойствам префикс-функции &amp;lt;tex&amp;gt; s'[p[n]] = s'[n] &amp;lt;/tex&amp;gt; {{---}} суффикс и префикс строки &amp;lt;tex&amp;gt; s' &amp;lt;/tex&amp;gt; длины &amp;lt;tex&amp;gt; p[n] &amp;lt;/tex&amp;gt; продолжаются одним символом, значит, надо на текущую позицию строки &amp;lt;tex&amp;gt; s &amp;lt;/tex&amp;gt; поставить символ &amp;lt;tex&amp;gt; s[p[n]] &amp;lt;/tex&amp;gt;. Если значение префикс-функции увеличивается, значит, текущим символом продолжается префикс длины &amp;lt;tex&amp;gt; p[n - 1] &amp;lt;/tex&amp;gt;, а из свойств следует, что &amp;lt;tex&amp;gt; p[n - 1] \geqslant p[n] - 1 &amp;lt;/tex&amp;gt;. По предположению индукцию значение &amp;lt;tex&amp;gt; q[n - 1] &amp;lt;/tex&amp;gt; будет вычислено верно. А если значение префикс-функции не увеличивается, значит, символ &amp;lt;tex&amp;gt; s[n] &amp;lt;/tex&amp;gt; должен продолжить префикс меньшей длины, а в текущее значение префикс-функции запишется как раз длина нового бордера. Для этого будут использованы значения префикс-функции с меньшими индексами, которые посчитаны верно, опять же по препдположению индукции.&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
* Кормен Т., Лейзерсон Ч., Ривест Р. Алгоритмы: построение и анализ. {{---}} 2-е изд. {{---}} М.: Издательский дом «Вильямс», 2007. {{---}} С. 1296 ISBN 978-5-8459-0857-5&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Поиск подстроки в строке]]&lt;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B5%D1%84%D0%B8%D0%BA%D1%81-%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D1%8F&amp;diff=36971</id>
		<title>Префикс-функция</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B5%D1%84%D0%B8%D0%BA%D1%81-%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D1%8F&amp;diff=36971"/>
				<updated>2014-05-13T19:45:08Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: /* Эффективный алгоритм */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition = '''Префикс-функция''' ''(prefix-function)'' от строки(обозначается &amp;lt;tex&amp;gt;\pi(s,i)&amp;lt;/tex&amp;gt;) - длина наибольшего префикса строки &amp;lt;tex&amp;gt;S[1..i]&amp;lt;/tex&amp;gt;, который не совпадает с этой строкой и одновременно является ее суффиксом}}&lt;br /&gt;
&lt;br /&gt;
Префикс-функция строки &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; {{---}} функция &amp;lt;tex&amp;gt;\pi(s, i) = \max\limits_{k = 1..i - 1} \{ 0, k : &amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;s[1..k] = s[i - k + 1..i] \}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Здесь и далее считаем, что символы в строках нумеруются с &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
==Наивный алгоритм==&lt;br /&gt;
Наивный алгоритм вычисляет префикс функцию непосредственно по определению, сравнивая префиксы и суффиксы строк.&lt;br /&gt;
&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
 '''Prefix_function''' (&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;)&lt;br /&gt;
      &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt; = [0,..,0]&lt;br /&gt;
      '''for''' i = 1 '''to''' n&lt;br /&gt;
          '''for''' k = 1 '''to''' i - 1&lt;br /&gt;
              '''if''' s[1..k] == s[i - k + 1..i]&lt;br /&gt;
                  &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;[i] = k&lt;br /&gt;
      '''return''' &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
Рассмотрим строку abcabcd, для которой значение префикс-функции равно &amp;lt;tex&amp;gt;[0,0,0,1,2,3,0]&amp;lt;/tex&amp;gt;.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Шаг || Строка || Значение функции&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; || a || 0&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; || ab || 0&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt; || abc || 0&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt; || abca || 1&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt; || abcab || 2&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;6&amp;lt;/tex&amp;gt; || abcabc || 3&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt;7&amp;lt;/tex&amp;gt; || abcabcd || 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Время работы===&lt;br /&gt;
Всего &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; итераций цикла, на каждой из который происходит сравнение строк за &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;, что дает в итоге &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Эффективный алгоритм==&lt;br /&gt;
Вносятся несколько важных замечаний:&lt;br /&gt;
*Заметим, что &amp;lt;tex&amp;gt;\pi[i + 1] \le \pi[i] + 1&amp;lt;/tex&amp;gt;. Чтобы показать это, рассмотрим суффикс,оканчивающийся на позиции &amp;lt;tex&amp;gt;i + 1&amp;lt;/tex&amp;gt; и имеющий длину &amp;lt;tex&amp;gt;\pi[i + 1]&amp;lt;/tex&amp;gt;, удалив из него последний символ, мы получим суффикс, оканчивающийся на позиции &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; и имеющий длину &amp;lt;tex&amp;gt;\pi[i + 1] - 1&amp;lt;/tex&amp;gt;, следовательно неравенство &amp;lt;tex&amp;gt;\pi[i + 1] &amp;gt; \pi[i] + 1&amp;lt;/tex&amp;gt; неверно.&lt;br /&gt;
*Избавимся от явных сравнений строк. Пусть мы вычислили &amp;lt;tex&amp;gt;\pi[i]&amp;lt;/tex&amp;gt;, тогда, если &amp;lt;tex&amp;gt;s[i + 1] = s[\pi[i]]&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\pi[i + 1] = \pi[i] + 1&amp;lt;/tex&amp;gt;. Если окажется, что &amp;lt;tex&amp;gt;s[i + 1] \ne s[\pi[i]]&amp;lt;/tex&amp;gt;, то нужно попытаться попробовать подстроку меньшей длины. Для этого подберем такое &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;, что &amp;lt;tex&amp;gt;k = \pi(i) - 1&amp;lt;/tex&amp;gt;. Делаем это следующим образом. За исходное &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; необходимо взять &amp;lt;tex&amp;gt;\pi(i - 1)&amp;lt;/tex&amp;gt;, что следует из первого пункта. В случае, когда символы &amp;lt;tex&amp;gt;s[k+1]&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;s[i]&amp;lt;/tex&amp;gt; не совпадают, &amp;lt;tex&amp;gt;\pi(k)&amp;lt;/tex&amp;gt; {{---}} следующее потенциальное наибольшее значение &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;, что видно из рисунка. Последнее утверждение верно, пока &amp;lt;tex&amp;gt;k&amp;gt;0&amp;lt;/tex&amp;gt;, что позволит всегда найти его следующее значение. Если &amp;lt;tex&amp;gt;k=0&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\pi(i)=1&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;s[i] = s[1]&amp;lt;/tex&amp;gt; , иначе &amp;lt;tex&amp;gt;\pi(i)=0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Prefix2.jpg‎]]&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
 '''Prefix_function''' (&amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;)&lt;br /&gt;
      &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;[1] = 0&lt;br /&gt;
      k = 0&lt;br /&gt;
      '''for''' i = 2 '''to''' n&lt;br /&gt;
          '''while''' k &amp;gt; 0 &amp;amp;&amp;amp; s[i] != s[k + 1]&lt;br /&gt;
              k = &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;[k]&lt;br /&gt;
          '''if''' s[i] == s[k + 1]&lt;br /&gt;
              k++&lt;br /&gt;
          &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;[i] = k&lt;br /&gt;
      '''return''' &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Время работы===&lt;br /&gt;
Время работы алгоритма составит &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для доказательства этого нужно заметить, что итоговое количество итераций цикла &amp;lt;tex&amp;gt;while&amp;lt;/tex&amp;gt; определяет асимптотику алгоритма. Теперь стоит отметить, что &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; увеличивается на каждом шаге не более чем на единицу, значит максимально возможное значение &amp;lt;tex&amp;gt;k = n - 1&amp;lt;/tex&amp;gt;. Поскольку внутри цикла &amp;lt;tex&amp;gt;while&amp;lt;/tex&amp;gt; значение &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; лишь уменьшается, получается, что &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; не может суммарно уменьшиться больше, чем &amp;lt;tex&amp;gt;n-1&amp;lt;/tex&amp;gt; раз. Значит цикл &amp;lt;tex&amp;gt;while&amp;lt;/tex&amp;gt; в итоге выполнится не более &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; раз, что дает итоговую оценку времени алгоритма &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Построение строки по префикс-функции==&lt;br /&gt;
===Постановка задачи=== &lt;br /&gt;
Восстановить строку по префикс-функции за &amp;lt;tex&amp;gt;O(N)&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;s&amp;lt;/tex&amp;gt; будет записан ответ. Пойдем по массиву &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; слева направо.&lt;br /&gt;
&lt;br /&gt;
Пусть мы хотим узнать значение &amp;lt;tex&amp;gt;s[i]&amp;lt;/tex&amp;gt;. Для этого посмотрим на значение &amp;lt;tex&amp;gt;p[i]&amp;lt;/tex&amp;gt;: если &amp;lt;tex&amp;gt;p[i] =0&amp;lt;/tex&amp;gt; тогда в &amp;lt;tex&amp;gt;s[i]&amp;lt;/tex&amp;gt; запишем новый символ, иначе &amp;lt;tex&amp;gt;s[i] = s[p[i]]&amp;lt;/tex&amp;gt;. Обратим внимание, что  &amp;lt;tex&amp;gt;s[p[i]]&amp;lt;/tex&amp;gt; нам уже известно, так как &amp;lt;tex&amp;gt;p[i] &amp;lt; i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Реализация ===&lt;br /&gt;
 '''string''' buildFromPrefix('''int'''[] p):&lt;br /&gt;
   s = &amp;quot;&amp;quot; &lt;br /&gt;
   '''for''' i = 0 '''to''' p.length - 1&lt;br /&gt;
       '''if''' p[i] == 0     &lt;br /&gt;
           s += new character&lt;br /&gt;
       '''else'''&lt;br /&gt;
           s += s[p[i]]&lt;br /&gt;
   '''return''' s&lt;br /&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;s'&amp;lt;/tex&amp;gt; правильная строка, строку &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; построил наш алгоритм, &amp;lt;tex&amp;gt; q &amp;lt;/tex&amp;gt; массив значений префикс-функции для &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Докажем корректность индукцией по длине массива префикс-функции полученной строки. Для начала заметим, что на предыдущие значения массива &amp;lt;tex&amp;gt; q &amp;lt;/tex&amp;gt; прибавление нового символа не влияет, так как при подсчёте префикс-функции на &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;-ой позиции рассматриваются символы на позициях не больше &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;. Поэтому достаточно показать, что очередное значение префикс-функции будет вычислено правильно.&lt;br /&gt;
* База очевидна для строки длины &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* Переход: пусть до &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;-ой позиции мы построили строку, что &amp;lt;tex&amp;gt;p[1..n - 1] = q[1..n - 1]&amp;lt;/tex&amp;gt;. Возможны два случая:&lt;br /&gt;
**  &amp;lt;tex&amp;gt;p[n] = 0&amp;lt;/tex&amp;gt;. Тогда мы добавляем новый символ, поэтому &amp;lt;tex&amp;gt;q[n]&amp;lt;/tex&amp;gt; тоже будет равно &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;. &lt;br /&gt;
** &amp;lt;tex&amp;gt;p[n] &amp;gt; 0&amp;lt;/tex&amp;gt;. По свойствам префикс-функции &amp;lt;tex&amp;gt; s'[p[n]] = s'[n] &amp;lt;/tex&amp;gt; {{---}} суффикс и префикс строки &amp;lt;tex&amp;gt; s' &amp;lt;/tex&amp;gt; длины &amp;lt;tex&amp;gt; p[n] &amp;lt;/tex&amp;gt; продолжаются одним символом, значит, надо на текущую позицию строки &amp;lt;tex&amp;gt; s &amp;lt;/tex&amp;gt; поставить символ &amp;lt;tex&amp;gt; s[p[n]] &amp;lt;/tex&amp;gt;. Если значение префикс-функции увеличивается, значит, текущим символом продолжается префикс длины &amp;lt;tex&amp;gt; p[n - 1] &amp;lt;/tex&amp;gt;, а из свойств следует, что &amp;lt;tex&amp;gt; p[n - 1] \geqslant p[n] - 1 &amp;lt;/tex&amp;gt;. По предположению индукцию значение &amp;lt;tex&amp;gt; q[n - 1] &amp;lt;/tex&amp;gt; будет вычислено верно. А если значение префикс-функции не увеличивается, значит, символ &amp;lt;tex&amp;gt; s[n] &amp;lt;/tex&amp;gt; должен продолжить префикс меньшей длины, а в текущее значение префикс-функции запишется как раз длина нового бордера. Для этого будут использованы значения префикс-функции с меньшими индексами, которые посчитаны верно, опять же по препдположению индукции.&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
* Кормен Т., Лейзерсон Ч., Ривест Р. Алгоритмы: построение и анализ. {{---}} 2-е изд. {{---}} М.: Издательский дом «Вильямс», 2007. {{---}} С. 1296 ISBN 978-5-8459-0857-5&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Поиск подстроки в строке]]&lt;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A8%D1%82%D0%BE%D1%80-%D0%92%D0%B0%D0%B3%D0%BD%D0%B5%D1%80%D0%B0_%D0%BD%D0%B0%D1%85%D0%BE%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B8%D0%BD%D0%B8%D0%BC%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B3%D0%BE_%D1%80%D0%B0%D0%B7%D1%80%D0%B5%D0%B7%D0%B0&amp;diff=34981</id>
		<title>Алгоритм Штор-Вагнера нахождения минимального разреза</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A8%D1%82%D0%BE%D1%80-%D0%92%D0%B0%D0%B3%D0%BD%D0%B5%D1%80%D0%B0_%D0%BD%D0%B0%D1%85%D0%BE%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B8%D0%BD%D0%B8%D0%BC%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B3%D0%BE_%D1%80%D0%B0%D0%B7%D1%80%D0%B5%D0%B7%D0%B0&amp;diff=34981"/>
				<updated>2014-01-03T08:18:46Z</updated>
		
		<summary type="html">&lt;p&gt;217.197.6.98: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Необходимые определения ==&lt;br /&gt;
&amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt; - неориентированный взвешенный граф с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершинами и &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; ребрами.&lt;br /&gt;
{{Определение |definition=&lt;br /&gt;
'''Разрезом''' называется такое разбиение множества &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt; на два подмножества &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt;, что:&lt;br /&gt;
* &amp;lt;tex&amp;gt;A, B \subset V&amp;lt;/tex&amp;gt;;&lt;br /&gt;
* &amp;lt;tex&amp;gt;A, B \neq \emptyset&amp;lt;/tex&amp;gt;;&lt;br /&gt;
* &amp;lt;tex&amp;gt;A \cap B = \emptyset&amp;lt;/tex&amp;gt;;&lt;br /&gt;
* &amp;lt;tex&amp;gt;A \cup B = V&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение |definition=&lt;br /&gt;
'''Весом разреза''' называется сумма весов рёбер, проходящих через разрез, т.е. таких рёбер, один конец которых принадлежит &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, а второй конец - &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* &amp;lt;tex&amp;gt;w(A, B) =&amp;lt;/tex&amp;gt; &amp;lt;tex dpi = &amp;quot;140&amp;quot;&amp;gt;\sum\limits_{uv \in E, u \in A, v \in B} w(u, v)&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Эту задачу называют &amp;quot;глобальным минимальным разрезом&amp;quot;. Глобальный минимальный разрез равен минимуму среди разрезов минимальной стоимости по всевозможным парам исток-сток. Хотя эту задачу можно решить с помощью любого алгоритма нахождения максимального потока (запуская его &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; раз для всевозможных пар истока и стока), однако ниже описан гораздо более простой и быстрый алгоритм, предложенный Матильдой Штор (Mechthild Stoer) и Франком Вагнером (Frank Wagner) в 1994 г.&lt;br /&gt;
&lt;br /&gt;
В общем случае допускаются петли и кратные рёбра, все кратные рёбра можно заменить одним ребром с их суммарным весом а петли не влияют на решение. Поэтому будем считать, что кратных ребер и петель во входном графе нет.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм == &lt;br /&gt;
Идея алгоритма довольно проста. Будем &amp;lt;tex&amp;gt;n-1&amp;lt;/tex&amp;gt; раз повторять следующий процесс: находить минимальный разрез между какой-нибудь парой вершин &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;, а затем объединять эти две вершины в одну (создавать новую вершину, список смежности которой равен объединению списков смежности &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;). В конце концов, после &amp;lt;tex&amp;gt;n-1&amp;lt;/tex&amp;gt; итерации, останется одна вершина. После этого ответом будет являться минимальный среди всех &amp;lt;tex&amp;gt;n-1&amp;lt;/tex&amp;gt; найденных разрезов. Действительно, на каждой &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ой стадии найденный минимальный разрез &amp;lt;tex&amp;gt;\langle A,B \rangle&amp;lt;/tex&amp;gt; между вершинами &amp;lt;tex&amp;gt;s_i&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;t_i&amp;lt;/tex&amp;gt; либо окажется искомым глобальным минимальным разрезом, либо же, напротив, вершины &amp;lt;tex&amp;gt;s_i&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;t_i&amp;lt;/tex&amp;gt; невыгодно относить к разным множествам, поэтому мы ничего не ухудшаем, объединяя эти две вершины в одну.&lt;br /&gt;
&lt;br /&gt;
Следовательно нам необходимо для данного графа найти минимальный разрез между какой-нибудь парой вершин &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;. Для этого вводим некоторое множество вершин &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, которое изначально содержит единственную произвольную вершину &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. На каждом шаге находится вершина, наиболее сильно связанная с множеством &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, т.е. вершина &amp;lt;tex&amp;gt;v \not\in A&amp;lt;/tex&amp;gt;, для которой следующая величина &amp;lt;tex dpi = &amp;quot;140&amp;quot;&amp;gt;w(v,A) = \sum\limits_{(v,u) \in E, \atop u \in A} w(v,u)&amp;lt;/tex&amp;gt; максимальна (максимальна сумма весов рёбер, один конец которых &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;, а другой принадлежит &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;). Этот процесс завершится, когда все вершины перейдут в множество &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 minCut(граф G):&lt;br /&gt;
   v[i] - список вершин, которые были сжаты в i-тую (сначала заполняется i);&lt;br /&gt;
   for i = 1..n-1&lt;br /&gt;
     A = Ø;&lt;br /&gt;
     fill(w, 0);&lt;br /&gt;
     for j = 1..n-1&lt;br /&gt;
       s = {s &amp;lt;tex&amp;gt;\in&amp;lt;/tex&amp;gt; V | s &amp;lt;tex&amp;gt;\notin&amp;lt;/tex&amp;gt; A, w[s] - max};&lt;br /&gt;
       if (j != n-1)&lt;br /&gt;
         A += s;&lt;br /&gt;
         пересчитываем связность w[i] для остальных вершин; &lt;br /&gt;
         prev = s;&lt;br /&gt;
       else&lt;br /&gt;
         if (w[s] &amp;lt; minCost)&lt;br /&gt;
           minCost = w[s];&lt;br /&gt;
           minCut = v[s];&lt;br /&gt;
         s' = s &amp;lt;tex&amp;gt;\cup&amp;lt;/tex&amp;gt; prev;&lt;br /&gt;
   return minCut - список вершин в минимальном разрезе;&lt;br /&gt;
&lt;br /&gt;
== Корректность алгоритма ==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
Если добавить в множество &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; по очереди все вершины, каждый раз добавляя вершину, наиболее сильно связанную с &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, то пусть предпоследняя добавленная вершина {{---}} &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;, а последняя {{---}} &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;. Тогда минимальный &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-&amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; разрез состоит из единственной вершины {{---}} &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Рассмотрим произвольный &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-&amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; разрез &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; и покажем, что его вес не может быть меньше веса разреза, состоящего из единственной вершины &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;:&lt;br /&gt;
 &lt;br /&gt;
: &amp;lt;tex dpi = '130'&amp;gt;w (\{t\}) \le w (C)&amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; - вершина, которую мы хотим добавить в &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, тогда &amp;lt;tex&amp;gt;A_v&amp;lt;/tex&amp;gt; - состояние множества &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; в этот момент. Пусть &amp;lt;tex&amp;gt;C_v&amp;lt;/tex&amp;gt; - разрез множества &amp;lt;tex&amp;gt;A_v \cup v&amp;lt;/tex&amp;gt;, индуцированный разрезом &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;. Вершина &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; - активная, если она и предыдущая добавленная вершина в &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; принадлежат разным частям разреза &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;, тогда для любой такой вершины:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;tex dpi = '130'&amp;gt;w (v, A_v) \le w (C_v)&amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; - активная вершина, для нее выполняется:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;tex dpi = '130'&amp;gt;w (t,A_t) \le w (C_t)&amp;lt;/tex&amp;gt; &lt;br /&gt;
: &amp;lt;tex dpi = '130'&amp;gt;w (t,A_t) = w (\{t\}), w (C_t) = w (C)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Получили утверждение теоремы.&lt;br /&gt;
Для доказательства воспользуемся методом математической индукции.&lt;br /&gt;
Для первой активной вершины &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; это неравенство верно, так как все вершины &amp;lt;tex&amp;gt;A_v&amp;lt;/tex&amp;gt; принадлежат одной части разреза, а &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; -  другой. Пусть неравенство выполнено для всех активных вершин до &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;, включая &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;, докажем его для следующей активной вершины &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;tex dpi = '130'&amp;gt; w (u,A_u) \equiv w (u,A_v) + w (u,A_u \setminus A_v)&amp;lt;/tex&amp;gt; (*)&lt;br /&gt;
&lt;br /&gt;
Заметим, что &lt;br /&gt;
&lt;br /&gt;
: &amp;lt;tex dpi = '130'&amp;gt;w (u,A_v) \le w (v,A_v)&amp;lt;/tex&amp;gt; (**)&lt;br /&gt;
&lt;br /&gt;
вершина &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; имела большее значение &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;, чем &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;, так как была добавлена в &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; раньше.&lt;br /&gt;
По предположению индукции:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;tex dpi = '130'&amp;gt;w (v,A_v) \le w (C_v)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Следовательно из (**):&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;tex dpi = '130'&amp;gt;w(u,A_v) \le w(C_v)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
А из (*) имеем:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;tex dpi = '130'&amp;gt;w (u,A_u) \le w (C_v) + w (u,A_u \setminus A_v)&amp;lt;/tex&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Вершина &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;A_u \setminus A_v&amp;lt;/tex&amp;gt; находятся в разных частях разреза &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt;, значит &amp;lt;tex&amp;gt;w (u,A_u \setminus A_v)&amp;lt;/tex&amp;gt; равна сумме весов ребер, которые не входят в &amp;lt;tex&amp;gt;C_v&amp;lt;/tex&amp;gt;, но входят в &amp;lt;tex&amp;gt;C_u&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;tex dpi = '130'&amp;gt;w (u,A_u) \le w (C_v) + w (u,A_u \setminus A_v) \le w (C_u)&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;w&amp;lt;/tex&amp;gt; за &amp;lt;tex&amp;gt;O (n)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;n-1&amp;lt;/tex&amp;gt; фаза по &amp;lt;tex&amp;gt;n-1&amp;lt;/tex&amp;gt; итерации в каждой. В итоге имеем &amp;lt;tex&amp;gt;O (n^3)&amp;lt;/tex&amp;gt;&lt;br /&gt;
#Если использовать фибоначчиевы кучи для нахождения вершины с наибольшей &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;, то асимптотика составит &amp;lt;tex&amp;gt;O (nm + n^2 \log n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
#Если использовать двоичные кучи, то асимптотика составит &amp;lt;tex&amp;gt;O (nm \log n + n^2)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Применение ==&lt;br /&gt;
Нахождение разреза минимальной стоимости является основой в одном из методов сегментации изображений (сегментацией изображения называется разбиение его на некоторые области, непохожие по некоторому признаку). &lt;br /&gt;
&lt;br /&gt;
Изображение представляется в виде взвешенного графа, вершинами которого являются точки изображения (скорее всего пиксели но может и области чуть больше, от этого зависит качество сегментации, а также скорость ее построения). Вес ребра представляет отражает &amp;quot;разницу&amp;quot; между точками(расстояние по некоторой введенной метрике). Разбиение изображения на однородные области сводится к задаче поиска минимального разреза в графе. Специально для такого рода задач был предложен метод нахождения разреза минимальной стоимости [https://www.google.ru/url?sa=t&amp;amp;rct=j&amp;amp;q=&amp;amp;esrc=s&amp;amp;source=web&amp;amp;cd=2&amp;amp;ved=0CDQQFjAB&amp;amp;url=http%3A%2F%2Fwww.cs.berkeley.edu%2F~malik%2Fpapers%2FSM-ncut.pdf&amp;amp;ei=cP2-UuqhAuSJ4gTnhYCwAg&amp;amp;usg=AFQjCNFn9GZPlFjDUgDofCScu6Wm47qMWQ&amp;amp;sig2=Yufd8LreEQKHe3NGnFVm7A&amp;amp;bvm=bv.58187178,d.bGE&amp;amp;cad=rjt Метод Normalized Cut Normalized Cut(J. Shi, J. Malik (1997))]&lt;br /&gt;
&lt;br /&gt;
== Источники ==&lt;br /&gt;
* [http://e-maxx.ru/bookz/files/stoer_wagner_mincut.pdf Mechthild Stoer, Frank Wagner. A Simple Min-Cut Algorithm]&lt;br /&gt;
* [http://e-maxx.ru/algo/stoer_wagner_mincut Алгоритм Штор-Вагнера]&lt;br /&gt;
* [http://cgm.computergraphics.ru/content/view/147 Методы сегментации изображения]&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
*[[Алгоритм Каргера для нахождения минимального разреза]]&lt;br /&gt;
*[https://www.google.ru/url?sa=t&amp;amp;rct=j&amp;amp;q=&amp;amp;esrc=s&amp;amp;source=web&amp;amp;cd=2&amp;amp;ved=0CDQQFjAB&amp;amp;url=http%3A%2F%2Fwww.cs.berkeley.edu%2F~malik%2Fpapers%2FSM-ncut.pdf&amp;amp;ei=cP2-UuqhAuSJ4gTnhYCwAg&amp;amp;usg=AFQjCNFn9GZPlFjDUgDofCScu6Wm47qMWQ&amp;amp;sig2=Yufd8LreEQKHe3NGnFVm7A&amp;amp;bvm=bv.58187178,d.bGE&amp;amp;cad=rjt Метод Normalized Cut]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о максимальном потоке]]&lt;/div&gt;</summary>
		<author><name>217.197.6.98</name></author>	</entry>

	</feed>