Автомат Кнута-Морриса-Пратта — различия между версиями
YanaZimka (обсуждение | вклад) (Новая страница: «Автомат Кнута-Морриса-Пратта используется в алгоритмах связанных с поиском образца в те...») |
YanaZimka (обсуждение | вклад) |
||
Строка 1: | Строка 1: | ||
− | Автомат Кнута-Морриса-Пратта используется в алгоритмах связанных с поиском образца в тексте, в том числе в реальном времени. | + | [[Детерминированные_конечные_автоматы|Автомат]] Кнута-Морриса-Пратта используется в алгоритмах, связанных с поиском образца в тексте, в том числе в реальном времени. |
− | == | + | == Суффикс-функция == |
{{Определение | {{Определение | ||
− | |id = | + | |id = suffix_func |
− | |definition = | + | |definition = Для строки <tex>p</tex> длиной <tex>m</tex> функция <tex> \sigma_p \colon \Sigma^* \to \left\{1,2, \dots ,m\right\}</tex> называется '''суффикс-функцией''', если она сопоставляет любой строке <tex>x</tex>, состоящей из символов алфавита <tex>\Sigma</tex>, длину максимального суффикса <tex>x</tex>, являющегося префиксом <tex>p</tex>. |
− | |||
− | |||
− | |||
− | |||
− | |||
}} | }} | ||
+ | ==== Пример суффикс-функции ==== | ||
− | - | + | Пусть строка <tex>p</tex>="<tex>abaab</tex>". Вот несколько примеров значений суффикс-функции для нее. |
− | |||
− | |||
− | |||
− | |||
− | + | ;*<tex>\sigma_p("aba")=3</tex>. | |
− | + | :В данном случае вся строка является префиксом <tex>p</tex>. | |
− | + | ;*<tex>\sigma_p("bb")=0</tex>. | |
− | + | :В данном случае какой бы суффикс мы ни взяли, ни один из них не является префиксом <tex>p</tex>. | |
− | + | ;*<tex>\sigma_p("aaab")=2</tex>. | |
− | + | :В данном случае "<tex>ab</tex>" является префиксом <tex>p</tex>, а все суффиксы длиннее {{---}} нет. | |
− | |||
− | }} | ||
== Структура автомата == | == Структура автомата == | ||
− | Автомат строится на строке-образце <tex> | + | [[Детерминированные_конечные_автоматы|Автомат]] строится на строке-образце <tex>p</tex> длины <tex>m</tex>, которую в будущем мы будем искать в тексте. |
− | Для автомата Кнута-Морриса-Пратта: | + | Для [[Детерминированные_конечные_автоматы|автомата]] Кнута-Морриса-Пратта: |
* <tex>Q = \left\{0,1,...,m\right\}</tex> | * <tex>Q = \left\{0,1,...,m\right\}</tex> | ||
− | * <tex> | + | * <tex> s = 0 </tex> |
− | * <tex> | + | * <tex> T = \left\{m\right\} </tex> |
− | * <tex> \delta(q, a) = \sigma( | + | * <tex> \delta(q, a) = \sigma(p[1 \dots q] + a) </tex>, где <tex>q</tex> {{---}} это состояние, <tex>a</tex> {{---}} символ, по которому осуществляется переход, a "<tex>+</tex>" {{---}} операция конкатенации (<tex>p[1, 0] = \varepsilon </tex>). |
− | Таким образом, если часть текста, в котором мы ищем образец, уже пропущена через автомат, то текущее состояние отражает, сколько последних символов этой прочитанной части совпадает с началом нашего образца. Если мы пришли в допускающее состояние, значит последние m символов полностью совпадают с образцом и мы нашли включение. | + | Таким образом, если часть текста, в котором мы ищем образец, уже пропущена через [[Детерминированные_конечные_автоматы|автомат]], то текущее состояние отражает, сколько последних символов этой прочитанной части совпадает с началом нашего образца. Если мы пришли в допускающее состояние, значит последние <tex>m</tex> символов полностью совпадают с образцом и мы нашли включение. |
Заметим, что тот факт, что переход по символу осуществляется независимо от последующих, позволяет нам работать как с текстом, данным заранее, так и с текстом, который вводится в реальном времени. | Заметим, что тот факт, что переход по символу осуществляется независимо от последующих, позволяет нам работать как с текстом, данным заранее, так и с текстом, который вводится в реальном времени. | ||
− | |||
==== Пример автомата Кнута-Морриса-Пратта ==== | ==== Пример автомата Кнута-Морриса-Пратта ==== | ||
[[Файл:Kmp_aut_ex.png]] | [[Файл:Kmp_aut_ex.png]] | ||
Строка 54: | Строка 43: | ||
Для каждого состояния и каждого символа будем определять значение функции перехода из данного состояния по данному символу. Пусть текущее состояние <tex>q</tex>. При считывании каждого нового символа <tex>a</tex> из текста возможно два варианта развития событий: | Для каждого состояния и каждого символа будем определять значение функции перехода из данного состояния по данному символу. Пусть текущее состояние <tex>q</tex>. При считывании каждого нового символа <tex>a</tex> из текста возможно два варианта развития событий: | ||
− | + | <center>''Символ <tex>a</tex> совпадает с <tex>q + 1</tex> символом строки <tex>p</tex>.''</center> | |
− | Это значит, что число последних символов текста, совпадающих с началом образца увеличилось на 1. Значит переход осуществляется в следующее состояние. В этом случае <tex>\delta(q, a) = q + 1</tex>. | + | |
+ | * Это значит, что число последних символов текста, совпадающих с началом образца увеличилось на 1. Значит переход осуществляется в следующее состояние. В этом случае <tex>\delta(q, a) = q + 1</tex>. | ||
− | + | <center>''Символ <tex>a</tex> не совпадает с <tex>q + 1</tex> символом строки <tex>p</tex>.''</center> | |
− | |||
− | (<tex>\ | + | * Тогда заметим, что если к строке, являющейся максимальным [[Основные_определения,_связанные_со_строками#border|бордером]] предыдущего совпадения, добавить прочитанный символ, то как раз получится текущее окончание текста, совпадающее с началом образца. Таким образом, в этом случае <tex>\delta(q, a) = \delta(\pi_p(q), a)</tex>, где <tex>\pi_p(q)</tex> {{---}} [[Префикс-функция|префикс-функция]] для строки <tex>p</tex>. Исключением для этого случая является лишь нулевое состояние. Если считанный символ не совпадает с первым символом образца, то мы останемся в нулевом состоянии, так как по прежнему совпадением является пустая строка. |
− | Исключением для этого случая является лишь нулевое состояние. Если считанный символ не совпадает с первым символом образца, то мы останемся в нулевом состоянии, так как по прежнему совпадением является пустая строка. | ||
=== Асимптотика === | === Асимптотика === | ||
Строка 69: | Строка 57: | ||
=== Псевдокод === | === Псевдокод === | ||
− | '''for''' q = 0 '''to''' m | + | '''function''' make_kmp() |
− | + | '''for''' q = 0 '''to''' m | |
− | + | '''for''' a <tex>\in \Sigma</tex> | |
− | + | '''if''' q > 0 '''and''' a <tex>\ne</tex> p[q + 1] | |
− | + | <tex>\delta</tex>(q, a) = <tex>\delta</tex>(<tex>\pi</tex>(q), a) | |
− | + | '''if''' c = p[q + 1] | |
− | + | <tex>\delta</tex>(q, a) = q + 1 | |
− | + | '''else''' | |
+ | <tex>\delta</tex>(q, a) = q | ||
+ | |||
+ | == Сравнение с другими алгоритмами поиска образца в тексте == | ||
+ | |||
+ | При решении задачи поиска всех включений образца в текст также часто применяются алгоритмы Ахо-Корасик и Кнута-Морриса-Пратта. | ||
+ | |||
+ | Алгоритм Ахо-Корасик использует автомат, построенный на основе приведенного здесь, и является расширением рассматриваемого алгоритма. Он применяется в несколько иных случаях {{---}} когда образцов для поиска несколько. И решает эту задачу быстрее, чем построение нескольких автоматов Кнута-Морриса-Пратта. | ||
+ | |||
+ | Алгоритм Кнута-Морриса-Пратта решает ту же задачу, что и алгоритм с применением одноименного автомата. Однако он не может работать с текстом, вводимым в режиме реального времени, ему нужно заранее знать текст, в котором нужно искать образец. Также, если текст достаточно объемный, алгоритм Кнута-Морриса-Пратта будет использовать гораздо больше памяти, чем приведенный выше в данной статье. Однако, если текст небольшой и дан заранее, алгоритм Кнута-Морриса-Пратта будет работать быстрее. | ||
== См. также == | == См. также == | ||
*[[Алгоритм Ахо-Корасик]] | *[[Алгоритм Ахо-Корасик]] | ||
+ | *[[Алгоритм Кнута-Морриса-Пратта]] | ||
== Источники информации == | == Источники информации == | ||
*[[wikipedia:Finite-state_machine|Wikipedia {{---}} Finite-state machine]] | *[[wikipedia:Finite-state_machine|Wikipedia {{---}} Finite-state machine]] | ||
− | *ISBN 978-5-8459-1794-2 '''Томас Кормен, Чарльз Лейзерсон, Рональд Ривест, Клиффорд Штайн''' {{---}} Алгоритмы. Построение и анализ. | + | *ISBN 978-5-8459-1794-2 '''Томас Кормен, Чарльз Лейзерсон, Рональд Ривест, Клиффорд Штайн''' {{---}} Алгоритмы. Построение и анализ, стр. 771{{---}}776. |
+ | |||
+ | [[Категория: Алгоритмы и структуры данных]] | ||
+ | [[Категория: Поиск подстроки в строке]] | ||
+ | [[Категория: Автоматы и регулярные языки]] |
Версия 00:29, 16 июня 2015
Автомат Кнута-Морриса-Пратта используется в алгоритмах, связанных с поиском образца в тексте, в том числе в реальном времени.
Содержание
Суффикс-функция
Определение: |
Для строки | длиной функция называется суффикс-функцией, если она сопоставляет любой строке , состоящей из символов алфавита , длину максимального суффикса , являющегося префиксом .
Пример суффикс-функции
Пусть строка
=" ". Вот несколько примеров значений суффикс-функции для нее.- .
- В данном случае вся строка является префиксом .
- .
- В данном случае какой бы суффикс мы ни взяли, ни один из них не является префиксом .
- .
- В данном случае " " является префиксом , а все суффиксы длиннее — нет.
Структура автомата
Автомат строится на строке-образце длины , которую в будущем мы будем искать в тексте.
Для автомата Кнута-Морриса-Пратта:
- , где — это состояние, — символ, по которому осуществляется переход, a " " — операция конкатенации ( ).
Таким образом, если часть текста, в котором мы ищем образец, уже пропущена через автомат, то текущее состояние отражает, сколько последних символов этой прочитанной части совпадает с началом нашего образца. Если мы пришли в допускающее состояние, значит последние символов полностью совпадают с образцом и мы нашли включение.
Заметим, что тот факт, что переход по символу осуществляется независимо от последующих, позволяет нам работать как с текстом, данным заранее, так и с текстом, который вводится в реальном времени.
Пример автомата Кнута-Морриса-Пратта
Данный автомат построен для образца "
" и алфавитаПостроение автомата
Идея алгоритма
Для каждого состояния и каждого символа будем определять значение функции перехода из данного состояния по данному символу. Пусть текущее состояние
. При считывании каждого нового символа из текста возможно два варианта развития событий:- Это значит, что число последних символов текста, совпадающих с началом образца увеличилось на 1. Значит переход осуществляется в следующее состояние. В этом случае .
- Тогда заметим, что если к строке, являющейся максимальным бордером предыдущего совпадения, добавить прочитанный символ, то как раз получится текущее окончание текста, совпадающее с началом образца. Таким образом, в этом случае , где — префикс-функция для строки . Исключением для этого случая является лишь нулевое состояние. Если считанный символ не совпадает с первым символом образца, то мы останемся в нулевом состоянии, так как по прежнему совпадением является пустая строка.
Асимптотика
В данном алгоритме нам нужно лишь вычислить значение функции перехода в каждом состоянии для каждого символа. При предподсчитанной за
префикс-функции вычисление для одного состояния и одного символа происходит за . Всего состояний , а символов . Итого .Псевдокод
function make_kmp() for q = 0 to m for aif q > 0 and a p[q + 1] (q, a) = ( (q), a) if c = p[q + 1] (q, a) = q + 1 else (q, a) = q
Сравнение с другими алгоритмами поиска образца в тексте
При решении задачи поиска всех включений образца в текст также часто применяются алгоритмы Ахо-Корасик и Кнута-Морриса-Пратта.
Алгоритм Ахо-Корасик использует автомат, построенный на основе приведенного здесь, и является расширением рассматриваемого алгоритма. Он применяется в несколько иных случаях — когда образцов для поиска несколько. И решает эту задачу быстрее, чем построение нескольких автоматов Кнута-Морриса-Пратта.
Алгоритм Кнута-Морриса-Пратта решает ту же задачу, что и алгоритм с применением одноименного автомата. Однако он не может работать с текстом, вводимым в режиме реального времени, ему нужно заранее знать текст, в котором нужно искать образец. Также, если текст достаточно объемный, алгоритм Кнута-Морриса-Пратта будет использовать гораздо больше памяти, чем приведенный выше в данной статье. Однако, если текст небольшой и дан заранее, алгоритм Кнута-Морриса-Пратта будет работать быстрее.
См. также
Источники информации
- Wikipedia — Finite-state machine
- ISBN 978-5-8459-1794-2 Томас Кормен, Чарльз Лейзерсон, Рональд Ривест, Клиффорд Штайн — Алгоритмы. Построение и анализ, стр. 771—776.