Алгоритм Мориса-Кнута-Пратта на Java: подробное описание и примеры

Алгоритм Мориса-Кнута-Пратта (МКП) – это алгоритм поиска подстроки в строке, который является одним из наиболее эффективных алгоритмов. Он был разработан троечью ученых: Д. Морисом, В. Кнутом и Д. Праттом в 1977 году. МКП находит свое применение в обработке текстов и в реализации различных алгоритмов.

Основной принцип МКП заключается в использовании уже имеющейся информации о подстроке в строке, чтобы избежать лишних сравнений. Для этого строится таблица префиксов, которая содержит информацию о возможных правильных суффиксах подстроки. Эта таблица используется для оптимизации алгоритма.

Для реализации алгоритма на Java необходимо иметь понимание о работе и структуре МКП. В этой статье будет подробно описано, как работает МКП и как его реализовать на Java. Также будет приведен пример реализации алгоритма на Java с пошаговым объяснением. После прочтения этой статьи вы сможете использовать алгоритм МКП для решения задач поиска подстроки в строке на Java.

Алгоритм Мориса-Кнута-Пратта на Java

Алгоритм Мориса-Кнута-Пратта (МКП) является одним из наиболее распространённых алгоритмов поиска подстроки в строке. Он использует такую же идею, как и алгоритм Бойера-Мура, а именно — пропускать некоторые символы, используя знания о том, что подстрока искомой строки не может быть там расположена.

Кроме того, алгоритм МКП является алгоритмом линейного времени O(n+m), где n — длина текста, а m — длина подстроки. Это означает, что время работы алгоритма не зависит от размера алфавита и в худшем случае может быть равно O(nm).

Алгоритм МКП на Java реализуется следующим образом. Сначала создаются два массива: префикс-функция и таблица переходов. Префикс-функция — это массив, в котором для каждой позиции i хранится длина максимального собственного суффикса подстроки s[0:i], совпадающего с её префиксом. Таблица переходов — это двумерный массив, в котором для каждой позиции i и символа c хранится позиция, на которую нужно перейти, если в этой позиции встретился символ c.

Затем производится перебор символов в тексте и подстроке, где при совпадении символов индекс смещается на 1, а при несовпадении — используется таблица переходов, которая позволяет пропустить несколько символов за один шаг. Если все символы подстроки были найдены, то считается, что она найдена в тексте.

Приведём пример реализации алгоритма МКП на Java:

public class KnuthMorrisPratt {

public static int kmp(String text, String pattern) {

int n = text.length();

int m = pattern.length();

if (m == 0) {

return 0;

}

int[] lps = computePrefixFunction(pattern);

int j = 0;

for (int i = 0; i < n; ++i) {

while (j > 0 && pattern.charAt(j) != text.charAt(i)) {

j = lps[j - 1];

}

if (pattern.charAt(j) == text.charAt(i)) {

++j;

}

if (j == m) {

return i - m + 1;

}

}

return -1;

}

private static int[] computePrefixFunction(String pattern) {

int m = pattern.length();

int[] pi = new int[m];

int j = 0;

for (int i = 1; i < m; ++i) {

while (j > 0 && pattern.charAt(j) != pattern.charAt(i)) {

j = pi[j - 1];

}

if (pattern.charAt(j) == pattern.charAt(i)) {

++j;

}

pi[i] = j;

}

return pi;

}

}

В этом примере метод kmp выполняет поиск подстроки pattern в тексте text и возвращает индекс первого вхождения. Если подстрока не найдена, то возвращается -1. Метод computePrefixFunction вычисляет префикс-функцию для подстроки pattern.

Краткое описание

Алгоритм Мориса-Кнута-Пратта (МКП) является классическим алгоритмом для поиска подстроки в строке и применяется во многих областях, таких как текстовой анализ, биоинформатика, базы данных и многих других.

Алгоритм основан на эффективном поиске префиксов, суффиксов и граней строки-образца, что позволяет пропустить лишние сравнения и снизить сложность алгоритма.

Основными шагами алгоритма являются построение таблицы префиксов, поиск соответствия строки-образца в строке текста и обработка символов для сравнения.

Алгоритм МКП имеет линейную временную сложность и является более эффективным, чем наивный алгоритм поиска подстроки. Он также может быть оптимизирован для поиска нескольких подстрок одновременно и поиска в потоках данных.

В целом, алгоритм МКП является надежным и эффективным способом поиска подстроки в строке и является важным инструментом для анализа текстов и обработки данных.

Как работает алгоритм

Алгоритм Мориса-Кнута-Пратта используется для поиска всех вхождений заданного образца в строке. Он основывается на понятии префикса и суффикса, а также использовании таблицы префикс-суффиксов.

При поиске образца в строке алгоритм перебирает символы строки по порядку, сравнивая их с символами образца. Если символы не совпадают, алгоритм использует таблицу префикс-суффиксов для определения следующей позиции, с которой нужно продолжить сравнение символов.

Таблица префикс-суффиксов представляет собой массив, в котором для каждой позиции образца записана длина максимального общего префикса и суффикса, оканчивающихся в этой позиции. Если в образце нет префикса, совпадающего с суффиксом, то для данной позиции таблица содержит 0.

Алгоритм Мориса-Кнута-Пратта работает за линейное время, то есть затрачивает время, пропорциональное длине строки. Это делает его эффективным для поиска образцов в больших объемах данных.

Основные преимущества

Эффективность

Алгоритм Мориса-Кнута-Пратта позволяет находить все вхождения искомой подстроки в тексте за линейное время, то есть в худшем случае алгоритм пройдет не более, чем n+m шагов, где n – длина текста, а m – длина искомой подстроки. Это делает алгоритм одним из самых эффективных алгоритмов поиска подстроки.

Простота реализации

По сравнению с другими алгоритмами поиска подстроки, например, алгоритмом Кнута-Морриса-Пратта (КМП), алгоритм Мориса-Кнута-Пратта (МКП) имеет более простую реализацию. Реализация МКП не требует создания дополнительной таблицы-префиксов, как в случае с КМП.

Удобство использования

Алгоритм Мориса-Кнута-Пратта можно использовать для различных задач, связанных с поиском подстроки в тексте, таких как:

  • Поиск всех вхождений подстроки в тексте;
  • Проверка наличия подстроки в тексте;
  • Поиск наибольшей общей подстроки двух строк;
  • Преобразование регулярного выражения в конечный автомат.

Безопасность

Алгоритм Мориса-Кнута-Пратта не имеет уязвимостей к атакам типа DoS (отказ в обслуживании). Это связано с тем, что он не использует рекурсию, что делает его безопасным в использовании.

Реализация алгоритма Мориса-Кнута-Пратта на Java

Алгоритм Мориса-Кнута-Пратта (МКП) – это алгоритм поиска подстроки в строке. Для реализации данного алгоритма на языке Java необходимо создать метод, который будет принимать на вход образец (подстроку) и исходную строку, а затем выполнять поиск.

Основная идея МКП-алгоритма заключается в использовании префикс-функции, которая предварительно вычисляется для образца. Префикс-функция определяет максимальный суффикс подстроки, который также является её префиксом.

Псевдокод для реализации алгоритма МКП на Java:

public static List kmp(String pattern, String text) {

  • // вычисление префикс-функции для образца
  • List matches = new ArrayList();
  • // поиск вхождений
  •    return matches;

}

В данном методе префикс-функция вычисляется с помощью цикла, который проходит по каждому символу образца. Во время прохода определяется длина максимального суффикса текущей подстроки, который также является её префиксом.

Затем выполняется поиск вхождений путем сопоставления символов образца и исходной строки. В случае совпадения символов продолжается сравнение до тех пор, пока не будет найдено полное совпадение образца в исходной строке. Все найденные позиции сохраняются в списке matches.

Таким образом, реализация алгоритма Мориса-Кнута-Пратта на языке Java позволяет эффективно и быстро находить подстроки в строках, что является важным для решения многих задач в программировании и анализе данных.

Импорт библиотек

Перед написанием алгоритма Мориса-Кнута-Пратта на Java необходимо импортировать соответствующие библиотеки. В данном алгоритме используется только стандартная библиотека языка Java, поэтому нам не придется устанавливать дополнительные библиотеки.

  1. java.io.* — библиотека для работы с потоками ввода-вывода. Нам потребуется для считывания входной строки.
  2. java.util.* — библиотека, содержащая утилиты и коллекции. Нам будет нужна коллекция ArrayList, чтобы создать список префиксов.

Пример использования импортируемых библиотек:

Import statementОписание
import java.io.*;Импорт библиотеки для работы с потоками ввода-вывода
import java.util.*;Импорт библиотеки, содержащей утилиты и коллекции

Все необходимые библиотеки импортированы и мы готовы к написанию алгоритма Мориса-Кнута-Пратта на Java.

Описание класса Matcher

Класс Matcher — это класс, который представляет объект, используемый для выполнения сопоставления по шаблону в строке.

Он является частью пакета java.util.regex и работает с регулярными выражениями. Matcher позволяет находить по шаблону определенные подстроки в строке, на основе которых можно дальше выполнять другие действия.

Чтобы создать объект Matcher, необходимо сначала создать регулярное выражение с помощью класса Pattern, а затем вызвать у созданного выражения метод matcher().

У объекта Matcher есть несколько методов, которые используются для работы с совпадениями. Например:

  • matches() — проверяет, соответствует ли вся строка регулярному выражению;
  • find() — ищет следующее совпадение в строке;
  • group() — возвращает последний найденный фрагмент строки, соответствующий регулярному выражению, и т.д.

Кроме того, объект Matcher содержит информацию о последнем найденном совпадении в строке, а также о позиции в строке, на которой он найден. Данная информация доступна через методы start() и end().

В целом, класс Matcher представляет собой удобный и мощный инструмент для работы с регулярными выражениями в Java.

Использование метода find() и group()

Метод find() в Java используется для поиска первого вхождения заданного шаблона в строке. Он возвращает объект типа Matcher, с помощью которого можно получить информацию о найденном совпадении.

Для получения самого совпадения, а также его позиции в строке, можно использовать методы group() и start(). Метод group() возвращает строку, соответствующую найденному совпадению, а метод start() возвращает его позицию в исходной строке.

Если в шаблоне используются скобки, то можно получить информацию о найденных группах. Каждая группа обозначается своим номером, начиная с 1. Чтобы получить содержимое группы, можно использовать методы group(int group) или group(String group).

Например, если задано регулярное выражение «([A-Z]{2})(\d{3})», то найденное совпадение можно получить следующим образом:

  1. Объявляем строку, в которой будем искать совпадение: String str = «AB123CD456»;
  2. Создаем объект Pattern, передав в него регулярное выражение: Pattern pattern = Pattern.compile(«([A-Z]{2})(\d{3})»);
  3. Используем метод find() для поиска совпадения: Matcher matcher = pattern.matcher(str); if (matcher.find()) { … }
  4. Используем методы group() для получения информации о найденном совпадении: String match = matcher.group(); int position = matcher.start();
  5. Используем методы group(int group) или group(String group) для получения содержимого групп: String group1 = matcher.group(1); String group2 = matcher.group(2);

Примеры использования

Алгоритм Мориса-Кнута-Пратта широко используется для поиска подстрок в строке. Например, при разработке поисковиков, теговых редакторов и других приложений.

Давайте рассмотрим пример поиска подстроки в строке, используя алгоритм Мориса-Кнута-Пратта на языке Java:

public static int search(String text, String pattern) {

int l = pattern.length();

int n = text.length();

int[] prefix = prefixFunction(pattern);

int j = 0;

for (int i = 0; i < n; i++) {

while (j > 0 && pattern.charAt(j) != text.charAt(i)) {

j = prefix[j-1];

}

if (pattern.charAt(j) == text.charAt(i)) {

j++;

}

if (j == l) {

return i - l + 1;

}

}

return -1;

}

Этот код ищет вхождение строки pattern в строке text. Если вхождение найдено, функция возвращает позицию первого символа вхождения. Если вхождение не найдено, функция возвращает -1.

Если вам нужно найти все вхождения подстроки, вы можете использовать модифицированный алгоритм:

public static List<Integer> findAll(String text, String pattern) {

int l = pattern.length();

int n = text.length();

int[] prefix = prefixFunction(pattern);

List<Integer> positions = new ArrayList<>();

int j = 0;

for (int i = 0; i < n; i++) {

while (j > 0 && pattern.charAt(j) != text.charAt(i)) {

j = prefix[j-1];

}

if (pattern.charAt(j) == text.charAt(i)) {

j++;

}

if (j == l) {

positions.add(i - l + 1);

j = prefix[j-1];

}

}

return positions;

}

Эта функция возвращает список всех позиций вхождений подстроки pattern в строке text.

Наконец, вы можете использовать алгоритм Мориса-Кнута-Пратта для поиска всех периодических повторов в строке. Например, если ваша строка состоит из повторов подстроки «abc» через пробел, вы можете использовать такой код:

public static List<Integer> findPeriodicRepeats(String text) {

int[] prefix = prefixFunction(text);

int n = text.length();

List<Integer> periods = new ArrayList<>();

int p = n - prefix[n-1];

if (n % p == 0) {

periods.add(p);

}

for (int i = 2; i <= n; i++) {

if (prefix[i-1] == prefix[n-1] && (i - prefix[i-1]) % p == 0) {

periods.add(i - prefix[i-1]);

}

}

return periods;

}

Эта функция ищет периодически повторяющиеся части в строке text и возвращает список их длин.

Поиск подстроки в строке

Поиск подстроки в строке – одна из классических задач, которая часто возникает в различных задачах программирования. Эта задача заключается в том, чтобы найти в строке определенный фрагмент символов, который мы называем подстрокой.

Для поиска подстроки в строке существуют различные алгоритмы. Один из самых известных и эффективных алгоритмов – алгоритм Мориса-Кнута-Пратта (МКП). Он основан на использовании префикс-функции, которая позволяет ускорить поиск подстроки в строке.

Как работает алгоритм МКП? Сначала необходимо вычислить префикс-функцию для заданной строки. Затем мы пройдем по строке, которую нам нужно искать, и сравниваем каждый символ с символами в исходной строке. Если символы совпали, то мы продолжаем сравнение до тех пор, пока не найдем всю подстроку.

Алгоритм МКП является очень быстрым и эффективным способом поиска подстроки в строке. Он широко используется в программировании для решения различных задач, связанных с обработкой текста.

Вот пример использования алгоритма МКП на Java:

Исходная строкаПодстрока для поискаРезультат
«Hello, world!»«world»Найдено
«Java is a programming language»«C++»Не найдено
«JavaScript is awesome»«script»Не найдено

Проверка корректности email

Корректность email-адреса можно проверить путем использования регулярных выражений. Регулярное выражение представляет собой шаблон, который сопоставляется с подстрокой, и ищет соответствия. Для проверки email-адреса можно использовать следующее регулярное выражение:

[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}

Данное выражение проверяет наличие одного или нескольких символов, а затем «@» и доменное имя. В доменном имени должна быть как минимум одна точка и не менее двух символов. Также возможно добавление других условий в регулярное выражение в зависимости от конкретных требований к email-адресам.

Для проверки email-адреса в Java можно использовать метод matches(), который принимает на вход регулярное выражение. Вот пример:

String email = "[email protected]";

if (email.matches("[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}")) {

System.out.println("Email корректен");

} else {

System.out.println("Email некорректен");

}

Таким образом, используя регулярные выражения, можно легко проверить корректность email-адреса в Java. Эта техника может быть полезна при разработке приложений, где важно, чтобы пользователи вводили только корректные email-адреса.

FAQ

Какой алгоритм реализуется в статье?

В статье рассказывается о реализации алгоритма Мориса-Кнута-Пратта на языке Java.

Для чего используется алгоритм Мориса-Кнута-Пратта?

Алгоритм Мориса-Кнута-Пратта используется для поиска подстроки в строке. Он также известен как алгоритм КМП и является одним из самых эффективных алгоритмов для решения этой задачи.

Какие особенности реализации алгоритма описываются в статье?

Статья содержит подробное описание реализации алгоритма Мориса-Кнута-Пратта на языке Java. В ней объясняется, как работает алгоритм, и дается пример его использования.

Можно ли использовать алгоритм Мориса-Кнута-Пратта для работы со строками на других языках программирования?

Да, алгоритм Мориса-Кнута-Пратта можно реализовать на любом языке программирования. Однако, реализация алгоритма на разных языках может отличаться.

Какой минимальный уровень знаний программирования необходим для понимания статьи?

Для понимания статьи по алгоритму Мориса-Кнута-Пратта на Java нужно иметь начальные знания программирования и понимать основные конструкции языка Java, такие как циклы, условные операторы и работу со строками.

Ссылка на основную публикацию
Adblock
detector