11. Maximum Non-Overlapping Odd Palindrome Sum
β GFG solution to Maximum Non-Overlapping Odd Palindrome Sum problem: find maximum sum of lengths of two non-overlapping odd palindromes using Manacher's algorithm. π
The problem can be found at the following link: π Question Link
π§© Problem Description
Given a string s
consisting of lowercase English letters, find the maximum possible sum of the lengths of any two non-empty and non-overlapping palindromic substrings of odd length.
Formally, choose any two substrings s[i...j]
and s[k...l]
such that 1 β€ i β€ j < k β€ l β€ s.size()
, both substrings are palindromes of odd length, and they do not overlap. Return the maximum sum of their lengths.
Note: A palindrome is a string that reads the same forward and backward. A substring is a contiguous sequence of characters within the string.
π Examples
Example 1
Input: s = "xyabacbcz"
Output: 6
Explanation: "aba" and "cbc" are non-overlapping odd-length palindromes.
Their lengths are 3 and 3 which gives the sum as 6.
Example 2
Input: s = "gfgforgeeks"
Output: 4
Explanation: "gfg" and "g" are non-overlapping odd-length palindromes.
Their lengths are 3 and 1 which gives the sum as 4.
π Constraints
$2 \le s.size() \le 10^5$
String consists of lowercase English letters only
β
My Approach
The optimal approach uses Manacher's Algorithm combined with Dynamic Programming to efficiently find all palindromes and determine the maximum sum:
Manacher's Algorithm + Dynamic Programming
Palindrome Detection:
Use Manacher's algorithm to find all odd-length palindromes in linear time.
For each center position, compute the radius of the longest palindrome.
Left Segment Processing:
For each palindrome, mark its ending position with the palindrome length.
Propagate maximum lengths from right to left, ensuring we track the longest palindrome ending at or before each position.
Right Segment Processing:
For each palindrome, mark its starting position with the palindrome length.
Propagate maximum lengths from left to right, ensuring we track the longest palindrome starting at or after each position.
Optimal Split Point:
For each valid split position, combine the maximum palindrome from the left segment with the maximum palindrome from the right segment.
Return the maximum sum across all split points.
Key Insights:
Manacher's algorithm processes palindromes in O(n) time by avoiding redundant comparisons
Dynamic programming ensures we maintain optimal palindrome lengths for each segment
The algorithm handles edge cases by ensuring non-overlapping constraints
π Time and Auxiliary Space Complexity
Expected Time Complexity: O(n), where n is the length of the string. Manacher's algorithm runs in linear time, and the dynamic programming phases also process each position once.
Expected Auxiliary Space Complexity: O(n), as we use three arrays (left, right, rad) of size n to store palindrome information and segment maximums.
π§βπ» Code (C++)
class Solution {
public:
int maxSum(string& s) {
int n = s.size();
vector<int> left(n, 1), right(n, 1), rad(n);
for (int i = 0, l = 0, r = -1; i < n; i++) {
int k = (i > r) ? 1 : min(rad[l + r - i], r - i + 1);
while (i - k >= 0 && i + k < n && s[i - k] == s[i + k]) k++;
rad[i] = k--;
if (i + k > r) l = i - k, r = i + k;
}
for (int i = 0; i < n; i++) {
int len = rad[i] * 2 - 1;
int end = i + rad[i] - 1;
if (end < n) left[end] = max(left[end], len);
}
for (int i = n - 2; i >= 0; i--) left[i] = max(left[i], left[i + 1] - 2);
for (int i = 1; i < n; i++) left[i] = max(left[i], left[i - 1]);
for (int i = n - 1; i >= 0; i--) {
int len = rad[i] * 2 - 1;
int start = i - rad[i] + 1;
if (start >= 0) right[start] = max(right[start], len);
}
for (int i = 1; i < n; i++) right[i] = max(right[i], right[i - 1] - 2);
for (int i = n - 2; i >= 0; i--) right[i] = max(right[i], right[i + 1]);
int ans = 1;
for (int i = 0; i + 1 < n; i++) ans = max(ans, left[i] + right[i + 1]);
return ans;
}
};
β Code (Java)
class Solution {
public int maxSum(String s) {
int n = s.length();
int[] left = new int[n], right = new int[n], rad = new int[n];
Arrays.fill(left, 1);
Arrays.fill(right, 1);
for (int i = 0, l = 0, r = -1; i < n; i++) {
int k = (i > r) ? 1 : Math.min(rad[l + r - i], r - i + 1);
while (i - k >= 0 && i + k < n && s.charAt(i - k) == s.charAt(i + k)) k++;
rad[i] = k--;
if (i + k > r) { l = i - k; r = i + k; }
}
for (int i = 0; i < n; i++) {
int len = rad[i] * 2 - 1;
int end = i + rad[i] - 1;
if (end < n) left[end] = Math.max(left[end], len);
}
for (int i = n - 2; i >= 0; i--) left[i] = Math.max(left[i], left[i + 1] - 2);
for (int i = 1; i < n; i++) left[i] = Math.max(left[i], left[i - 1]);
for (int i = n - 1; i >= 0; i--) {
int len = rad[i] * 2 - 1;
int start = i - rad[i] + 1;
if (start >= 0) right[start] = Math.max(right[start], len);
}
for (int i = 1; i < n; i++) right[i] = Math.max(right[i], right[i - 1] - 2);
for (int i = n - 2; i >= 0; i--) right[i] = Math.max(right[i], right[i + 1]);
int ans = 1;
for (int i = 0; i + 1 < n; i++) ans = Math.max(ans, left[i] + right[i + 1]);
return ans;
}
}
π Code (Python)
class Solution:
def maxSum(self, s):
n = len(s)
left, right, rad = [1] * n, [1] * n, [0] * n
l, r = 0, -1
for i in range(n):
k = 1 if i > r else min(rad[l + r - i], r - i + 1)
while i - k >= 0 and i + k < n and s[i - k] == s[i + k]:
k += 1
rad[i] = k
k -= 1
if i + k > r:
l, r = i - k, i + k
for i in range(n):
length = rad[i] * 2 - 1
end = i + rad[i] - 1
if end < n:
left[end] = max(left[end], length)
for i in range(n - 2, -1, -1):
left[i] = max(left[i], left[i + 1] - 2)
for i in range(1, n):
left[i] = max(left[i], left[i - 1])
for i in range(n - 1, -1, -1):
length = rad[i] * 2 - 1
start = i - rad[i] + 1
if start >= 0:
right[start] = max(right[start], length)
for i in range(1, n):
right[i] = max(right[i], right[i - 1] - 2)
for i in range(n - 2, -1, -1):
right[i] = max(right[i], right[i + 1])
ans = 1
for i in range(n - 1):
ans = max(ans, left[i] + right[i + 1])
return ans
π§ Contribution and Support
For discussions, questions, or doubts related to this solution, feel free to connect on LinkedIn: π¬ Any Questions?. Let's make this learning journey more collaborative!
β If you find this helpful, please give this repository a star! β
πVisitor Count
Last updated