<?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=Maxina29</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=Maxina29"/>
		<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/Maxina29"/>
		<updated>2026-05-19T16:38:21Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Axo.jpg&amp;diff=71640</id>
		<title>Файл:Axo.jpg</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Axo.jpg&amp;diff=71640"/>
				<updated>2019-06-06T17:42:02Z</updated>
		
		<summary type="html">&lt;p&gt;Maxina29: Maxina29 загрузил новую версию Файл:Axo.jpg&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Maxina29</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Axo.jpg&amp;diff=71639</id>
		<title>Файл:Axo.jpg</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Axo.jpg&amp;diff=71639"/>
				<updated>2019-06-06T16:45:09Z</updated>
		
		<summary type="html">&lt;p&gt;Maxina29: Maxina29 загрузил новую версию Файл:Axo.jpg&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Maxina29</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%91%D0%BE%D1%80.jpg&amp;diff=71638</id>
		<title>Файл:Бор.jpg</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%91%D0%BE%D1%80.jpg&amp;diff=71638"/>
				<updated>2019-06-06T16:28:09Z</updated>
		
		<summary type="html">&lt;p&gt;Maxina29: Maxina29 загрузил новую версию Файл:Бор.jpg&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Maxina29</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%91%D0%BE%D1%80.jpg&amp;diff=71637</id>
		<title>Файл:Бор.jpg</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%91%D0%BE%D1%80.jpg&amp;diff=71637"/>
				<updated>2019-06-06T16:25:43Z</updated>
		
		<summary type="html">&lt;p&gt;Maxina29: Maxina29 загрузил новую версию Файл:Бор.jpg&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Maxina29</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_Shift-And&amp;diff=71636</id>
		<title>Алгоритм Shift-And</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_Shift-And&amp;diff=71636"/>
				<updated>2019-06-06T14:17:07Z</updated>
		
		<summary type="html">&lt;p&gt;Maxina29: Исправление ошибок с отображением \ldots, замена \cdot на \times при указании размера массива&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;В 1990ые годы Рикардо Беза-Йетс (англ. ''Ricardo Baeza-Yates'') и Гастон Гоннет (англ. ''Gaston Gonnet'') изобрели простой битовый метод, эффективно решающий задачу точного поиска малых образцов (длиной в типичное английское слово). Они назвали его методом &amp;lt;tex&amp;gt;Shift\texttt{-}And&amp;lt;/tex&amp;gt;. Также алгоритм известен как &amp;lt;tex&amp;gt;bitap&amp;lt;/tex&amp;gt; алгоритм и алгоритм Беза-Йетса-Гоннета. Существует вариация данного алгоритма под названием &amp;lt;tex&amp;gt;Shift\texttt{-}Or&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;n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;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;M&amp;lt;/tex&amp;gt; размером &amp;lt;tex&amp;gt;n \times (m + 1)&amp;lt;/tex&amp;gt;, в котором индекс &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; пробегает значения от &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;, а индекс &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt; {{---}} от &amp;lt;tex&amp;gt;0&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;M[i][j] = 1&amp;lt;/tex&amp;gt;, если первые &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; символов &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; точно совпадают с &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; символами &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;, кончаясь на позиции &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;; иначе &amp;lt;tex&amp;gt;M[i][j] = 0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; M[i][j] =&lt;br /&gt;
\left\{&lt;br /&gt;
	\begin{array}{ll}&lt;br /&gt;
		1, &amp;amp; \mbox {if p[1 $\ldots$ i] = t[j - i + 1 $\ldots$ j]} \\&lt;br /&gt;
		0, &amp;amp; \mbox {otherwise}&lt;br /&gt;
	\end{array}&lt;br /&gt;
\right.&lt;br /&gt;
&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Например, пусть &amp;lt;tex&amp;gt;t = california&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;p = for&amp;lt;/tex&amp;gt;. Тогда &amp;lt;tex&amp;gt;M[1][5] = M[2][6] = M[3][7] = 1&amp;lt;/tex&amp;gt;, остальные &amp;lt;tex&amp;gt;M[i][j] = 0&amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Получаем, что  элементы, равные &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;, в строчке &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; показывают все места в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;, где заканчиватся копии &amp;lt;tex&amp;gt;p[1 \ldots i]&amp;lt;/tex&amp;gt;, а столбец &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt; показывает все префиксы &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt;, которые заканчиваются в позиции &amp;lt;tex&amp;gt;j&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&amp;gt;M[n][j] = 1&amp;lt;/tex&amp;gt; тогда, когда вхождение &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; заканчивается в позиции &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt; строки &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;. &lt;br /&gt;
То есть вычисление последней строки &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; решает задачу точного совпадения.&lt;br /&gt;
 &lt;br /&gt;
=== Построение массива M ===&lt;br /&gt;
&lt;br /&gt;
Создадим для каждого символа алфавита &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; двоичный вектор &amp;lt;tex&amp;gt;U[x]&amp;lt;/tex&amp;gt; длины &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;U[x]&amp;lt;/tex&amp;gt; равно &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; в тех позициях &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt;, где стоит символ &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;. &lt;br /&gt;
Например, &amp;lt;tex&amp;gt;p = abacdeab&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;U[a] = 10100010&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Назовём вектором &amp;lt;tex&amp;gt;Bit\texttt{-}Shift(M[j])&amp;lt;/tex&amp;gt; такой вектор, который получен сдвигом столбца &amp;lt;tex&amp;gt;M[j]&amp;lt;/tex&amp;gt; вниз на одну позицию и записью &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; в первой позиции. Старое значение в позиции &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; теряется.&lt;br /&gt;
}}&lt;br /&gt;
 &lt;br /&gt;
То есть &amp;lt;tex&amp;gt;Bit\texttt{-}Shift(M[j])&amp;lt;/tex&amp;gt; состоит из &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;, к которой приписаны первые &amp;lt;tex&amp;gt;n - 1&amp;lt;/tex&amp;gt; битов столбца &amp;lt;tex&amp;gt;M[j]&amp;lt;/tex&amp;gt;. Например,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;(0, 0, 0, 1, 0, 1, 1, 0, 1) \overset{Bit\texttt{-}Shift}{\longmapsto} (1, 0, 0, 0, 1, 0, 1, 1, 0)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Из определения, нулевой столбец &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; состоит из нулей. Элементы любого другого столбца &amp;lt;tex&amp;gt;M[j],\ j &amp;gt; 0&amp;lt;/tex&amp;gt; получаются из столбца &amp;lt;tex&amp;gt;M[j - 1]&amp;lt;/tex&amp;gt; и вектора &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; для символа &amp;lt;tex&amp;gt;t[j]&amp;lt;/tex&amp;gt;. А именно, вектор для столбца &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt; получается операцией побитового логического умножения &amp;lt;tex&amp;gt;and&amp;lt;/tex&amp;gt; вектора &amp;lt;tex&amp;gt;Bit\texttt{-}Shift(M[j - 1])&amp;lt;/tex&amp;gt; и вектора &amp;lt;tex&amp;gt;U[t[j]]&amp;lt;/tex&amp;gt;. &lt;br /&gt;
&amp;lt;tex&amp;gt;M[j] = Bit\texttt{-}Shift(M[j - 1]) \ and \ U[t[j]]&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
&lt;br /&gt;
    '''string''' shiftAndSearch('''string''' text, '''string''' pattern):&lt;br /&gt;
        n = pattern.length&lt;br /&gt;
        m = text.length&lt;br /&gt;
        '''if''' n == 0&lt;br /&gt;
            '''return''' text&lt;br /&gt;
        M = array[n] of bit &amp;lt;font color=green&amp;gt;           // для поиска коротких слов достаточно одной переменной типа '''integer''' &amp;lt;/font&amp;gt;&lt;br /&gt;
        fill(M, 0)&lt;br /&gt;
        U = new array [&amp;lt;tex&amp;gt;|\Sigma|&amp;lt;/tex&amp;gt;][n] of bit &amp;lt;font color=green&amp;gt; // изначально все элементы равны &amp;lt;tex&amp;gt; 0 &amp;lt;/tex&amp;gt; &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''for''' i = 1..n &amp;lt;font color=green&amp;gt;                 // препроцессинг {{---}} вычисление вектора &amp;lt;tex&amp;gt; U &amp;lt;/tex&amp;gt; &amp;lt;/font&amp;gt;&lt;br /&gt;
            U[pattern[i]][i] = 1&lt;br /&gt;
        '''for''' j = 1..m&lt;br /&gt;
            M = Bit-Shift(M) '''&amp;amp;''' U[text[j]]&lt;br /&gt;
            '''if''' M[n]&lt;br /&gt;
                '''return''' text[j - n + 1..j]&lt;br /&gt;
        '''return''' null&lt;br /&gt;
&lt;br /&gt;
==Корректность==&lt;br /&gt;
Докажем, что метод &amp;lt;tex&amp;gt;Shift\texttt{-}And&amp;lt;/tex&amp;gt; правильно вычисляет элементы массива &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt;. Заметим, что для любого &amp;lt;tex&amp;gt;i &amp;gt; 1&amp;lt;/tex&amp;gt; элемент &amp;lt;tex&amp;gt;M[i][j] = 1&amp;lt;/tex&amp;gt; тогда и только тогда, когда &amp;lt;tex&amp;gt;p[1 \ldots i - 1]&amp;lt;/tex&amp;gt; совпадает с &amp;lt;tex&amp;gt; t[j - i + 1 \ldots j-1]&amp;lt;/tex&amp;gt;, а символ &amp;lt;tex&amp;gt;p[i]&amp;lt;/tex&amp;gt; совпадает с &amp;lt;tex&amp;gt;t[j]&amp;lt;/tex&amp;gt;. Первое условие выполнено, когда элемент массива &amp;lt;tex&amp;gt;M[i - 1][j - 1] = 1&amp;lt;/tex&amp;gt;, а второе — когда &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый бит вектора &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; для символа &amp;lt;tex&amp;gt;t[j]&amp;lt;/tex&amp;gt; равен &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;. Таким образом, чтобы вычислить элемент &amp;lt;tex&amp;gt; M[i][j] &amp;lt;/tex&amp;gt;, нужно взять результат побитовой операции &amp;lt;tex&amp;gt; and &amp;lt;/tex&amp;gt; элементов &amp;lt;tex&amp;gt; M[i - 1][j - 1] &amp;lt;/tex&amp;gt; и  &amp;lt;tex&amp;gt;U[t[j]][i]&amp;lt;/tex&amp;gt;. Это эквивалентно применению побитовой операции &amp;lt;tex&amp;gt; and &amp;lt;/tex&amp;gt; к вектору &amp;lt;tex&amp;gt; U[t[j]] &amp;lt;/tex&amp;gt; и сдвинутому на &amp;lt;tex&amp;gt; 1 &amp;lt;/tex&amp;gt; столбцу под номером &amp;lt;tex&amp;gt; j - 1 &amp;lt;/tex&amp;gt; массива &amp;lt;tex&amp;gt; M &amp;lt;/tex&amp;gt;. Для &amp;lt;tex&amp;gt; i = 1 &amp;lt;/tex&amp;gt; нам достаточно проверить, что &amp;lt;tex&amp;gt;U[t[j]][1] = 1 &amp;lt;/tex&amp;gt;, поэтому мы и записываем в &amp;lt;tex&amp;gt; M[1][j] &amp;lt;/tex&amp;gt; единицу, что и делает операция &amp;lt;tex&amp;gt; Bit\texttt{-}Shift &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(n \cdot m)&amp;lt;/tex&amp;gt;, на препроцессинг {{---}} построение массива &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; {{---}} требуется &amp;lt;tex&amp;gt;O(|\Sigma| \cdot n)&amp;lt;/tex&amp;gt; операций и памяти. Если же &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; не превышает длину машинного слова, то сложность получается &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;O(n + |\Sigma|)&amp;lt;/tex&amp;gt; соответсвенно.&lt;br /&gt;
&lt;br /&gt;
==Алгоритм Shift-Or==&lt;br /&gt;
Аналогичен алгоритму &amp;lt;tex&amp;gt;Shift\texttt{-}And&amp;lt;/tex&amp;gt;, но вместо массива &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; используется массив &amp;lt;tex&amp;gt;R&amp;lt;/tex&amp;gt;, определяемый следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; R[i][j] =&lt;br /&gt;
\left\{&lt;br /&gt;
	\begin{array}{ll}&lt;br /&gt;
		0, &amp;amp; \mbox {if p[1 $\ldots$ i] = t[j - i + 1 $\ldots$ j]} \\&lt;br /&gt;
		1, &amp;amp; \mbox {otherwise}&lt;br /&gt;
	\end{array}&lt;br /&gt;
\right.&lt;br /&gt;
&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Следующий столбец &amp;lt;tex&amp;gt;R[j]&amp;lt;/tex&amp;gt; получается операцией побитового логического сложения &amp;lt;tex&amp;gt;or&amp;lt;/tex&amp;gt; вектора &amp;lt;tex&amp;gt;Bit\texttt{-}Shift'(R[j - 1])&amp;lt;/tex&amp;gt; и вектора &amp;lt;tex&amp;gt;W[t[j]]&amp;lt;/tex&amp;gt;. Здесь &amp;lt;tex&amp;gt;W[t[j]] = not \ U[t[j]]&amp;lt;/tex&amp;gt;, а &amp;lt;tex&amp;gt;Bit\texttt{-}Shift'(R[j - 1])&amp;lt;/tex&amp;gt; {{---}} сдвиг вектора &amp;lt;tex&amp;gt;R[j - 1]&amp;lt;/tex&amp;gt; на одну позицию вниз с записью &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; в первой позиции.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;R[j] = Bit\texttt{-}Shift'(R[j - 1]) \ or \ W[t[j]]&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Очевидно, что алгоритм &amp;lt;tex&amp;gt;Shift\texttt{-}Or&amp;lt;/tex&amp;gt; корректен, так как данная формула получается применением логического отрицания к аналогичной формуле для алгоритма &amp;lt;tex&amp;gt;Shift\texttt{-}And&amp;lt;/tex&amp;gt;, корректность которого была доказана выше.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Z-функция]] &lt;br /&gt;
* [[Алгоритм Кнута-Морриса-Пратта]]&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
*''Дэн Гасфилд'' — '''Строки, деревья и последовательности в алгоритмах: Информатика и вычислительная биология''' — СПб.: Невский Диалект; БХВ-Петербург, 2003. — стр 100.&lt;br /&gt;
*[[wikipedia:Bitap algorithm | Wikipedia {{---}} Bitap algorithm]]&lt;br /&gt;
*[http://algolist.manual.ru/search/esearch/shift_or.php Алгоритм Shift-Or]&lt;br /&gt;
*[http://www-igm.univ-mlv.fr/~lecroq/string/node6.html Shift-Or algorithm]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Поиск подстроки в строке]]&lt;br /&gt;
[[Категория: Точный поиск]]&lt;/div&gt;</summary>
		<author><name>Maxina29</name></author>	</entry>

	</feed>