Найдовший підрядок паліндрому в рядку в Java

Найдовший підрядок паліндрому в рядку в Java

Вступ

У багатьох галузях комп’ютерних наук, таких як біоінформатика та обробка природної мови, постає задача пошуку найдовшого підрядка паліндрому в заданому рядку. Паліндром – це рядок, який читається однаково в обох напрямках, наприклад, “radar” або “kayak”.

Для вирішення цієї задачі розроблено різні алгоритми. Кожен алгоритм має свої переваги та недоліки залежно від конкретних потреб. У цій статті ми розглянемо один з найефективніших алгоритмів – алгоритм Манакера – і реалізуємо його за допомогою мови програмування Java.

Алгоритм Манакера

Алгоритм Манакера – це лінійний алгоритм, який розв’язує задачу пошуку найдовшого підрядка паліндрому за O(n) часу, де n – довжина заданого рядка. Алгоритм використовує дві техніки для оптимізації пошуку:

Попередня обробка рядка: Рядок розширюється спеціальними символами, зазвичай “$” на початку та “#” між кожною парою символів. Це дозволяє розглядати непарні та парні паліндроми однаково.
Використання таблиці радіусів: Таблиця радіусів зберігає радіуси паліндромів з центрами в кожній позиції рядка. Ця інформація використовується для швидкого розширення паліндромів та уникнення зайвих перевірок.

Реалізація алгоритму Манакера в Java

Нижче наведено реалізацію алгоритму Манакера в Java:

java
public class PalindromeSubstring {

public static String findLongestPalindrome(String str) {
// Попередня обробка рядка
StringBuilder sb = new StringBuilder("$#");
for (char c : str.toCharArray()) {
sb.append(c).append('#');
}
sb.append('$');
String expandedString = sb.toString();

// Ініціалізація таблиці радіусів
int[] radius = new int[expandedString.length()];

// Змінні для відстеження центру та правого кордону поточного найдовшого паліндрому
int center = 0;
int right = 0;

int maxRadius = 0;
int maxCenter = 0;

// Ітерація по рядку з розширеними символами
for (int i = 1; i < radius.length - 1; i++) {
// Обчислення радіусу поточного символу на основі поточного найдовшого паліндрому
radius[i] = Math.min(right - i, radius[2 * center - i]);

// Розширення паліндрому в обидва боки, поки це можливо
while (i - radius[i] - 1 >= 0 && i + radius[i] + 1 < radius.length &&
expandedString.charAt(i - radius[i] - 1) == expandedString.charAt(i + radius[i] + 1)) {
radius[i]++;
}

// Оновлення поточного найдовшого паліндрому, якщо новий паліндром більший
if (radius[i] > maxRadius) {
maxRadius = radius[i];
maxCenter = i;
}

// Оновлення правого кордону поточного найдовшого паліндрому
if (i + radius[i] > right) {
right = i + radius[i];
center = i;
}
}

// Вилучення найдовшого підрядка паліндрому з рядка з розширеними символами
return expandedString.substring(maxCenter - maxRadius - 1, maxCenter + maxRadius);
}

public static void main(String[] args) {
String str = "forgeeksskeegfor";
System.out.println(findLongestPalindrome(str)); // Виведе: forgeeksskeegfor
}
}

Результат роботи алгоритму

Алгоритм Манакера повертає найдовший підрядок паліндрому в заданому рядку. У прикладі, наведеному вище, найдовшим підрядком паліндрому є “forgeeksskeegfor”.

Переваги та недоліки алгоритму Манакера

Переваги:

– Лінійна часова складність O(n).
– Ефективний для пошуку як парних, так і непарних паліндромів.
– Застосовний до великих рядків завдяки оптимізаціям.

Недоліки:

– Використовує додатковий простір для таблиці радіусів.
– Може бути дещо складним для розуміння та реалізації.

Висновок

Алгоритм Манакера є ефективним способом пошуку найдовшого підрядка паліндрому в рядку в Java. Він відрізняється лінійною часовою складністю та може бути використаний для вирішення різних задач у галузі обробки рядків та інших областях. Хоча він має деякі недоліки, його переваги роблять його цінним інструментом для розв’язання задач такого типу.

Часті запитання

1. Яка часова складність алгоритму Манакера?
– Лінійна, O(n).

2. Чи може алгоритм Манакера знайти перекривні паліндроми?
– Ні, він знаходить лише найдовший неперекривний підрядок паліндрому.

3. Чи можна використовувати алгоритм Манакера для пошуку паліндромів у будь-якому символьному рядку?
– Так, він працює незалежно від того, містить рядок цифри, літери або будь-які інші символи.

4. Чи можна оптимізувати алгоритм Манакера ще більше?
– Так, існують покращені версії, наприклад, алгоритм Кнута-Морріса-Пратта (Knuth-Morris-Pratt, KMP), які можуть бути швидшими для певних випадків.

5. Чи є альтернативні алгоритми для пошуку найдовших підрядків паліндромів?
– Так, існують інші ефективні алгоритми, такі як алгоритм Манассе-Мейєра (Manasse-Myers) і алгоритм Гоарса-Шира (Horspool-Shier).

6. Для яких задач корисний алгоритм Манакера?
– Він використовується в біоінформатиці для аналізу ДНК-послідовностей, обробці природної мови для виявлення паліндромів у тексті та багатьох інших областях.

7. Чи можна реалізувати алгоритм Манакера на інших мовах програмування?
– Так, він може бути реалізований на більшості мовах програмування, включаючи C++, Python і C#.

8. Де можна знайти більше інформації про алгоритм Манакера?
– Тут наведені корисні ресурси:
Вікіпедія: Алгоритм Манакера
GeeksforGeeks: Алгоритм Манакера
LeetCode: Знайти найдовший підрядок паліндрому