Manacher's Algorithm
Learn via video course
Manacher's Algorithm
Abstract
Manacher's algorithm is used to find the longest palindromic substring in any string. It is required to solve sub-problems of some very hard problems. The problem statement it solves is: Given a string 's' with the length of 'n'. Find the longest palindromic substring in the given string. A string is a palindrome when it is equal to the reverse of itself.
Manacher's algorithm was invented by Manacher for listing all the palindromes that appear at the start of any given string, it was later observed that the same algorithm can be used to find the longest palindromic substring of any string in linear time.
Scope of the Article
- In this article, we will learn how to find the longest palindromic substring in any given string.
- We will discuss how to do it using the brute force approach and Manacher's algorithm.
- Every step in the algorithm will be explained thoroughly.
- Implementations will be explained using comments at each step.
- We will understand the Complexity Analysis of each implementation.
Takeaways
- Complexity of Manacher's algorithm
- Time complexity - .
Brute Force Approach
The brute force / naive approach is slower than Manacher's algorithm, but it is a good stepping stone for understanding the problem and Manacher's algorithm. The Brute force approach is to check each substring of the given string whether the substring is a palindrome or not.
To implement the brute force approach, first, we will use a nested loop to get each substring, and then nest another loop to check whether that substring is a palindrome or not.
Implementation in C++ 17
Implementation in Python 3
Implementation in Java 8
The output is the same for all of these (the implementation is the same, the difference is only of the programming languages).
Output
The Longest Palindromic Substring is: bddfddb
In the above examples, we are using the brute force approach to find the longest palindromic substring in the given string.
The printSubstring() function is used for printing a substring, longestPalSubstring() is used to print the longest palindromic substring.
Time Complexity:
In the brute force approach, three nested loops are used to find the longest palindromic substring, so the time complexity will be .
Space Complexity
No extra space is needed in this approach, so the space complexity will be .
Manacher’s algorithm
Manacher's algorithm is used to find the longest palindromic substring in any given string. This algorithm is faster than the brute force approach, as it exploits the idea of a palindrome happening inside another palindrome.
Manacher's algorithm is designed to find the palindromic substrings with odd lengths only. To use it for even lengths also, we tweak the input string by inserting the character "#" at the beginning and each alternate position after that (changing "abcaac" to "#a#b#c#a#a#c#").
In the case of an odd length palindrome, the middle character will be a character of the original string, surrounded by "#". In the case of an even length palindrome, the middle character will be a "#" character. Now we will learn each of its steps for a deeper understanding, which will help us in its implementation.
Steps of the Manacher's Algorithm
Steps of the Manacher's algorithm are as follows:
- Create an array or a list () of length which is ( being the length of the given string), to modify the given string.
- Assign the first and last element of to be "@" and "$", respectively.
- Fill the blank spaces in by characters of the given string and "#" alternatively.
- Declare variables
- Implicating maximum detected length of palindrome substring
- Position from where to start searching
- Highest position of the extreme right character of all detected palindromes
- Center of the detected palindrome .
- Create an array or a list to record the width of each palindrome about their center, center being the corresponding characters in .
- Create a for loop iterating from to , with incrementing in each iteration.
- In each iteration, check if , if yes, then assign minimum of and to .
- Nest a while loop inside the for loop, to count with width along the center, condition being, is equal to , if yes, increment by 1.
- To update center, check if is greater than , if yes, assign to be , and to be .
- For updating the Maximum length detected, check if is greater than , if yes, then assign to be , and to be .
- Come out of the for loop, and print the substring in the given string, starting from and ending at .
Implementation of Manacher's Algorithm
Now we will implement Manacher's algorithm in C++17, Java 8, and Python 3
Things to Note:
- is the length of the modified (after inserting extra characters) list/array.
- is the modified (after inserting extra characters) list/array.
- is the length of the longest palindrome detected.
- is the position from which we have to search for a palindrome.
- is the position of the rightmost character of a palindrome.
- is the center of a palindrome
- is the list/array of the width of palindromes about their center, center being the corresponding characters in .
Implementation in C++ 17
Implementation in Python 3
Implementation in Java 8
The output is the same for all of these (the implementation is the same, the difference is only of the programming languages).
Output
In the above examples, we are using the Manacher’s algorithm to find the longest palindromic substring in the given string.
The printSubstring() function is used for printing a substring, longestPalSubstring() is used to print the longest palindromic substring.
Complexity Analysis of Manacher’s Algorithm
Analysing the Time and Spatial complexity of Manacher's algorithm ( here is the number of characters inside the given string):
Time Complexity:
At the first glance, it may seem that the algorithm has a time complexity due to nested loops, but that's not the case, a more careful analysis shows that the algorithm is linear and amortized.
Each successful comparison results in moving one step forward, and it never reduces, therefore, the inner while loop gets executed at most times. Hence, the time complexity of Manacher's algorithm will be
Space Complexity:
We need space to create and form (palindrome width).
Conclusion
- Manacher's Algorithm is used to find the longest palindrome substring in a given string.
- Finding the longest palindrome using the Brute Force algorithm is very slow, time complexity being .
- The given string needs to be modified by inserting a special character at every alternate position to work it with Manacher's algorithm in every case.
- Time Complexity of Manacher's algorithm is .
- Space Complexity of Manacher's algorithm is .