After spending about 6-8 hours trying to digest the Manacher\'s algorithm, I am ready to throw in the towel. But before I do, here is one last shot in the dark: can anyone e
I went through the same frustration/struggle and I found the solution on this page, https://www.hackerearth.com/practice/algorithms/string-algorithm/manachars-algorithm/tutorial/, to be easiest to understand. I tried to implement this solution in my own style, and I think I can understand the algorithm now. I also tried to stuff as many explanations in the code as possible to explain the algo. Hope this help!
#Manacher's Algorithm
def longestPalindrome(s):
s = s.lower()
#Insert special characters, #, between characters
#Insert another special in the front, $, and at the end, @, of string to avoid bound checking.
s1 = '$#'
for c in s:
s1 += c + '#'
s1 = s1+'@'
#print(s, " -modified into- ", s1)
#Palin[i] = length of longest palindrome start at center i
Palin = [0]*len(s1)
#THE HARD PART: THE MEAT of the ALGO
#c and r help keeping track of the expanded regions.
c = r = 0
for i in range(1,len(s1)-1): #NOTE: this algo always expands around center i
#if we already expanded past i, we can retrieve partial info
#about this location i, by looking at the mirror from left side of center.
if r > i: #---nice, we look into memory of the past---
#look up mirror from left of center c
mirror = c - (i-c)
#mirror's largest palindrome = Palin[mirror]
#case1: if mirror's largest palindrome expands past r, choose r-i
#case2: if mirror's largest palindrome is contains within r, choose Palin[mirror]
Palin[i] = min(r-i, Palin[mirror])
#keep expanding around center i
#NOTE: instead of starting to expand from i-1 and i+1, which is repeated work
#we start expanding from Palin[i],
##which is, if applicable, updated in previous step
while s1[i+1+Palin[i]] == s1[i-1-Palin[i]]:
Palin[i] += 1
#if expanded past r, update r and c
if i+Palin[i] > r:
c = i
r = i + Palin[i]
#the easy part: find the max length, remove special characters, and return
max_center = max_length = 0
for i in range(len(s1)):
if Palin[i] > max_length:
max_length = Palin[i]
max_center = i
output = s1[max_center-max_length : max_center+max_length]
output = ''.join(output.split('#'))
return output # for the (the result substring)