Advertisement
Maximum Non-Overlapping Odd Palindrome Sum
JavaView on GFG
Maximum Non-Overlapping Odd Palindrome Sum.java
Java
import java.util.*;
class Solution {
public int maxSum(String s) {
int n = s.length();
if (n < 2)
return 0;
int[] d = manacherOdd(s);
int[] maxEnd = new int[n]; // best palindrome length ending exactly at i
int[] maxStart = new int[n]; // best palindrome length starting exactly at i
// Sweep left->right to compute maxEnd using a max-heap of linear contributions
PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> Integer.compare(b[0], a[0])); // [B, R]
int centerIdx = 0;
for (int e = 0; e < n; e++) {
while (centerIdx < n && centerIdx <= e) {
int c = centerIdx;
int B = 1 - 2 * c; // contribution constant for this center
int R = c + d[c] - 1; // rightmost end this center can cover
pq.offer(new int[] { B, R });
centerIdx++;
}
while (!pq.isEmpty() && pq.peek()[1] < e)
pq.poll(); // remove expired centers
if (!pq.isEmpty())
maxEnd[e] = 2 * e + pq.peek()[0]; // 2*e + B
else
maxEnd[e] = 1;
}
// prefix maxima: best palindrome length that ends at or before i
int[] maxPref = new int[n];
int cur = 0;
for (int i = 0; i < n; i++) {
if (maxEnd[i] > cur)
cur = maxEnd[i];
maxPref[i] = cur;
}
// Sweep right->left to compute maxStart using a max-heap of linear
// contributions
PriorityQueue<int[]> pq2 = new PriorityQueue<>((a, b) -> Integer.compare(b[0], a[0])); // [C, L]
int centerIdx2 = n - 1;
for (int sIdx = n - 1; sIdx >= 0; sIdx--) {
while (centerIdx2 >= 0 && centerIdx2 >= sIdx) {
int c = centerIdx2;
int C = 2 * c + 1; // contribution constant for this center
int L = c - d[c] + 1; // leftmost start this center can cover
pq2.offer(new int[] { C, L });
centerIdx2--;
}
while (!pq2.isEmpty() && pq2.peek()[1] > sIdx)
pq2.poll(); // remove expired
if (!pq2.isEmpty())
maxStart[sIdx] = -2 * sIdx + pq2.peek()[0]; // -2*s + C
else
maxStart[sIdx] = 1;
}
// suffix maxima: best palindrome length that starts at or after i
int[] maxSuff = new int[n];
cur = 0;
for (int i = n - 1; i >= 0; i--) {
if (maxStart[i] > cur)
cur = maxStart[i];
maxSuff[i] = cur;
}
// combine non-overlapping: split between i and i+1
int ans = 0;
for (int i = 0; i < n - 1; i++)
ans = Math.max(ans, maxPref[i] + maxSuff[i + 1]);
return ans;
}
private int[] manacherOdd(String s) {
int n = s.length();
int[] d = new int[n];
int l = 0, r = -1;
for (int i = 0; i < n; i++) {
int k = 1;
if (i <= r)
k = Math.min(d[l + r - i], r - i + 1);
while (i - k >= 0 && i + k < n && s.charAt(i - k) == s.charAt(i + k))
k++;
d[i] = k;
if (i + k - 1 > r) {
l = i - k + 1;
r = i + k - 1;
}
}
return d;
}
}
Advertisement
Was this solution helpful?