Skip to content

1960. Maximum Product of the Length of Two Palindromic Substrings

Description

You are given a 0-indexed string s and are tasked with finding two non-intersecting palindromic substrings of odd length such that the product of their lengths is maximized.

More formally, you want to choose four integers i, j, k, l such that 0 <= i <= j < k <= l < s.length and both the substrings s[i...j] and s[k...l] are palindromes and have odd lengths. s[i...j] denotes a substring from index i to index j inclusive.

Return the maximum possible product of the lengths of the two non-intersecting palindromic substrings.

A palindrome is a string that is the same forward and backward. A substring is a contiguous sequence of characters in a string.

 

Example 1:

Input: s = "ababbb"
Output: 9
Explanation: Substrings "aba" and "bbb" are palindromes with odd length. product = 3 * 3 = 9.

Example 2:

Input: s = "zaaaxbbby"
Output: 9
Explanation: Substrings "aaa" and "bbb" are palindromes with odd length. product = 3 * 3 = 9.

 

Constraints:

  • 2 <= s.length <= 105
  • s consists of lowercase English letters.

 

Solutions

Solution: Manacher’s Algorithm

  • Time complexity: O(n)
  • Space complexity: O(n)

 

JavaScript

js
/**
 * @param {string} s
 * @return {number}
 */
const maxProduct = function (s) {
  const n = s.length;

  const manacher = str => {
    const maxExtends = Array.from({ length: n }, () => 0);
    const leftToRight = Array.from({ length: n }, () => 1);
    let center = 0;

    for (let index = 0; index < n; index++) {
      const r = center + maxExtends[center] - 1;
      const mirrorIndex = center - (index - center);
      let extend = index > r ? 1 : Math.min(maxExtends[mirrorIndex], r - index + 1);

      while (index - extend >= 0 && index + extend < n && str[index - extend] === str[index + extend]) {
        leftToRight[index + extend] = 2 * extend + 1;
        extend += 1;
      }

      maxExtends[index] = extend;

      if (index + maxExtends[index] >= r) {
        center = index;
      }
    }

    for (let index = 1; index < n; index++) {
      leftToRight[index] = Math.max(leftToRight[index], leftToRight[index - 1]);
    }

    return leftToRight;
  };

  const maxLeft = manacher(s);
  const reversed = s.split('').reverse().join('');
  const maxRight = manacher(reversed).reverse();
  let reuslt = 1;

  for (let index = 1; index < n; index++) {
    reuslt = Math.max(reuslt, maxLeft[index - 1] * maxRight[index]);
  }

  return reuslt;
};

Released under the MIT license