Maximum length palindromic substring for every index such that it starts and ends at that index


In this article, we'll delve into a fascinating problem in the realm of string algorithms: how to find the maximum length palindromic substring for every index such that it starts and ends at that index in a string. This problem is an interesting challenge, especially for those interested in mastering the art of string manipulation in various programming languages.

A palindrome is a string that reads the same backward as forward. For example, "madam" is a palindrome. The challenge here is to find the longest palindromic substring for every index in a given string, where the substring starts and ends at that specific index.

Problem Statement

Given a string, find the maximum length palindromic substring for every index such that the substring starts and ends at that index.

Approach

The approach we'll use to solve this problem is called "Manacher's Algorithm". This algorithm works by expanding around the center and is known for its efficiency in finding the longest palindromic substring. It uses previously computed information to avoid redundant computation, which makes it significantly faster than naive solutions.

Example

Following are the implementations of this operation in various programming languages −

#include <stdio.h>
#include <string.h>

// Function to find the longest palindromic substring centered at each position
void findLongestPalindromicSubstring(char* s, int n, int* result) {
   int d1[n];
   for (int i = 0, l = 0, r = -1; i < n; i++) {
      int k = (i > r) ? 1 : (d1[l + r - i] < r - i + 1) ? d1[l + r - i] : r - i + 1;
      while (0 <= i - k && i + k < n && s[i - k] == s[i + k]) {
         k++;
      }
      d1[i] = k--;
      if (i + k > r) {
         l = i - k;
         r = i + k;
      }
   }
   memcpy(result, d1, sizeof(int) * n);
}

int main() {
   char s[] = "bananas";
   int n = strlen(s);
   int result[n];
   findLongestPalindromicSubstring(s, n, result);
   for (int i = 0; i < n; i++) {
      printf("Index: %d, String: %.*s, Length: %d\n", i, 2 * result[i] - 1, s + i - result[i] + 1, 2 * result[i] - 1);
   }
   return 0;
}

Output

Index: 0, String: b, Length: 1
Index: 1, String: a, Length: 1
Index: 2, String: ana, Length: 3
Index: 3, String: anana, Length: 5
Index: 4, String: ana, Length: 3
Index: 5, String: a, Length: 1
Index: 6, String: s, Length: 1
#include<bits/stdc++.h>
using namespace std;

vector<int> findLongestPalindromicSubstring(string s) {
   int n = s.size();
   vector<int> d1(n);
   for (int i = 0, l = 0, r = -1; i < n; i++) {
      int k = (i > r) ? 1 : min(d1[l + r - i], r - i + 1);
      while (0 <= i - k && i + k < n && s[i - k] == s[i + k]) {
         k++;
      }
      d1[i] = k--;
      if (i + k > r) {
         l = i - k;
         r = i + k;
      }
   }
   return d1;
}

int main() {
   string s = "bananas";
   vector<int> result = findLongestPalindromicSubstring(s);
   for(int i=0; i<s.size(); i++){
      cout << "Index: " << i << ", String: " << s.substr(i-result[i]+1, 2*result[i]-1) << ", Length: " << 2*result[i]-1 << "\n";
   }
   return 0;
}

Output

Index: 0, String: b, Length: 1
Index: 1, String: a, Length: 1
Index: 2, String: ana, Length: 3
Index: 3, String: anana, Length: 5
Index: 4, String: ana, Length: 3
Index: 5, String: a, Length: 1
Index: 6, String: s, Length: 1
import java.util.Arrays;

public class Main {
   public static int[] findLongestPalindromicSubstring(String s) {
      int n = s.length();
      int[] d1 = new int[n];
      int l = 0, r = -1;

      for (int i = 0; i < n; i++) {
         int k = (i > r) ? 1 : Math.min(d1[l + r - i], r - i + 1);

         while (i - k >= 0 && i + k < n && s.charAt(i - k) == s.charAt(i + k)) {
            k++;
         }

         d1[i] = k--;
            
         if (i + k > r) {
            l = i - k;
            r = i + k;
         }
      }
      return d1;
   }

   public static void main(String[] args) {
      String s = "bananas";
      int[] result = findLongestPalindromicSubstring(s);

      for (int i = 0; i < s.length(); i++) {
         String substring = s.substring(i - result[i] + 1, i + result[i]);
         System.out.println("Index: " + i + ", String: " + substring + ", Length: " + (2 * result[i] - 1));
      }
   }
}

Output

Index: 0, String: b, Length: 1
Index: 1, String: a, Length: 1
Index: 2, String: ana, Length: 3
Index: 3, String: anana, Length: 5
Index: 4, String: ana, Length: 3
Index: 5, String: a, Length: 1
Index: 6, String: s, Length: 1
# Function to find the longest palindromic substring centered at each position
def find_longest_palindromic_substring(s):
   n = len(s)
   d1 = [0] * n
   l, r = 0, -1  # Initialize l and r to 0 and -1, respectively
   for i in range(n):
      k = 1 if i > r else min(d1[l + r - i], r - i + 1)
      while 0 <= i - k and i + k < n and s[i - k] == s[i + k]:
         k += 1
      d1[i] = k - 1
      if i + k - 1 > r:
         l = i - k + 1
         r = i + k - 1
   return d1

if __name__ == "__main__":
   s = "bananas"
   result = find_longest_palindromic_substring(s)
   for i in range(len(s)):
      print(f"Index: {i}, String: {s[i-result[i]+1:i+result[i]+1]}, Length: {2*result[i]+1}")

Output

Index: 0, String: b, Length: 1
Index: 1, String: a, Length: 1
Index: 2, String: ana, Length: 3
Index: 3, String: anana, Length: 5
Index: 4, String: ana, Length: 3
Index: 5, String: a, Length: 1
Index: 6, String: s, Length: 1

The function findLongestPalindromicSubstring takes as input a string s and returns a vector of integers where each index i of the vector stores the maximum length of the palindromic substring starting and ending at index i in the string.

In this test case, the input string is "bananas". The findLongestPalindromicSubstring function is called with this string as the argument, and the result is stored in the result vector. Then, for each index, the corresponding maximum length palindromic substring is printed along with its length.

Conclusion

Finding the maximum length palindromic substring for every index in a string can be a challenging problem, but with the right algorithm at hand, such as Manacher's Algorithm, it can be solved efficiently. We hope this article has given you a clear understanding of how to approach and solve this problem.

Updated on: 23-Oct-2023

95 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements