Note for myself
- add special char just to partition them for expansion e.g.
#
→#A#B#B#C#
- initialise ⇒
maxRight=0, palindromLengths=[], center=0
- by looping it we check if the current
i
is within maxRight, if yes, we use amirror = center*2 - i
min(maxRight - i, p[mirror])
for the case when the part of palindrome is not starting from0
- and every loop just move the
maxRight
andcenter
wheni + p[i] > R
⇒maxRight = i + p[i], center=i
- case below is looking for the number of palindrome:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36const countSubstrings = (s) => { // Manacher's algorithm
let modifiedString = '#';
for (let i = 0; i < s.length; i++) {
modifiedString += s[i] + '#';
}
const n = modifiedString.length;
const P = new Array(n).fill(0);
let center = 0, right = 0;
let count = 0;
for (let i = 0; i < n; i++) {
if (i <= right) {
const mirror = 2 * center - i;
P[i] = Math.min(right - i, P[mirror]);
}
let leftIndex = i - (1 + P[i]);
let rightIndex = i + (1 + P[i]);
while (leftIndex >= 0 && rightIndex < n && modifiedString[leftIndex] === modifiedString[rightIndex]) {
P[i]++;
leftIndex--;
rightIndex++;
}
if (i + P[i] > right) {
center = i;
right = i + P[i];
}
count += Math.ceil(P[i] / 2);
}
return count;
};
rewind please its hard to actually memorise - do it again!
What is Manacher's Algorithm?
Manacher's algorithm is an efficient algorithm used to find the longest palindromic substring in a given string. It was invented by Gustav Manacher in 1975. The algorithm works by using the properties of palindromic substrings to avoid unnecessary comparisons, thereby reducing the overall time complexity.
Overall, Manacher's algorithm is a very elegant and efficient solution to the problem of finding the longest palindromic substring in a given string.
The algorithm uses two key ideas:
- Symmetry property: A palindrome has a symmetry around its
center
. If we already know the palindrome of acenter
, we can use it to avoid checking characters that cannot be part of a longer palindrome. - Dynamic Programming: We can use previous calculations to compute new ones.
The Manacher's algorithm has a time complexity of O(n), where n is the length of the string, which makes it very efficient.
Here's how the Manacher algorithm works:
Preprocess the input string
s
by inserting a special character, such as '#', between each pair of characters to make the string odd-length. For example, the string "abba" would become "#a#b#b#a#".Initialise two arrays:
P
, whereP[i]
stores the length of the longest palindromic substring centered ati
, andC
, whereC[i]
stores the center of the longest palindromic substring found so far.
Set a variable called
maxRight
to0
, which represents the rightmost boundary of the longest palindromic substring found so far, and setcenter
to0
, which represents its center.Iterate through the string
s
from left to right, and for each characteri
, do the following:If
i
is within the current palindromic substring (i.e., i <= maxRight), setP[i]
tomin(P[2 * center - i], maxRight - i)
, which means the palindrome centered ati
is a reflection of the palindrome centered at center.Expand the palindrome centered at
i
by comparing characterss[i - P[i] - 1]
ands[i + P[i] + 1]
. If they are equal, increaseP[i]
by1
.If the expanded palindrome centered at
i
extends beyondmaxRight
, updatemaxRight
andcenter
accordingly.
Find the maximum value in the
P
array, and its correspondingcenter
index. The longest palindromic substring is then the substring centered at this index, with lengthP[center] - 1
.
For myself
My workaround: usual case example of case where window is not starting form 0