Problem Link:
Difficulty:
Medium
Pre-requisites:
Manacher’s Algorithm
Problem:
Given a string in "compressed notation"(see problem), find the number of substrings that are palindrome.
Explanation:
The problem was a straightforward application of Manacher’s Algorithm. This Algo was originally proposed to find the longest palindrome in a string. However, for each "center" c, it finds the length of longest palindrome "centered" at c. Therefore, we can use it to find the number of palindromes "centered" at c as well. Handling the fact that strings are given in compressed notation is relatively straightforward.
Many elegant descriptions of Manacher’s Algorithm can be found on internet.
In very short, Manacher’s Algorithm can be written as follows.
1 | int p[N+1], mx = 0, id = 0;
2 | // length of longest palindrome centred at i is 2 * p[i]-1.
3 | for (i = 1; i <= N; i++) {
4 | p[i] = mx > i ? min(p[2 * id-i], mx-i) : 1;
5 | while (s[i + p[i]] == s[i - p[i]]) p[i]++;
6 | if (i + p[i] > mx) {
7 | mx = i + p[i];
8 | id = i;
9 | }
10| }
Let the compressed string be (c1, k1), (c2, k2), ... (cN, kN).
Assuming reader understands Manacher’s Algorithm, here is how to modify it for this problem:
Palindromes that contain only a single character repeated several times can be counted as:
Σ ki * (ki +1) / 2
Palindromes that span over more than 1 contiguous segment of compressed string can be computed by also maintaining an array q, which stores the length of the longest "decompressed" palindrome centred at ith segment.
q[i] = ki-p[i]+1 + ki-p[i]+2 ... + ki + ... ki+p[i]-2 + ki+p[i]-1
There will also be minor changes like:
1. We need not put interleaving '#'es because center of every palindromic substring is the center of some "compressed" segment(unless it fully lies inside a segment).
2. In line no 5, compare the characters as well as the lengths of the segments.
3. If the segments i-p[i] and i+p[i] do not have same lengths, but have the same character, then q[i] would need to adjusted by adding 2*min(ki-p[i], ki+p[i]).
The final Answer is
Σ ki * (ki +1) / 2 + ⌈q[i]/2⌉ - ⌈ki/2⌉
Setter's Solution:
Can be found here
Tester's Solution:
Can be found here