Back to all solutions

#1682 - Longest Palindromic Subsequence II

Problem Description

A subsequence of a string s is considered a good palindromic subsequence if:

  • It is a subsequence of s.
  • It is a palindrome (has the same value if reversed).
  • It has an even length.
  • No two consecutive characters are equal, except the two middle ones.

For example, if s = "abcabcabb", then "abba" is considered a good palindromic subsequence, while "bcb" (not even length) and "bbbb" (has equal consecutive characters) are not.

Given a string s, return the length of the longest good palindromic subsequence in s.

Solution

/**
 * @param {string} s
 * @return {number}
 */
var longestPalindromeSubseq = function(s) {
  const stringLength = s.length;
  const alphabetSize = 26;
  const baseCharCode = 97;

  const memoTable = new Array(alphabetSize + 1);
  for (let i = 0; i <= alphabetSize; i++) {
    const matrix = memoTable[i] = new Array(stringLength);
    for (let j = 0; j < stringLength; j++) {
      matrix[j] = new Array(stringLength);
    }
  }

  return findLongestPalindrome(alphabetSize, 0, stringLength - 1);

  function findLongestPalindrome(previousChar, leftIndex, rightIndex) {
    if (leftIndex >= rightIndex) return 0;

    const cachedResult = memoTable[previousChar][leftIndex][rightIndex];
    if (cachedResult !== undefined) return cachedResult;

    let maxLength = 0;
    const leftChar = s.charCodeAt(leftIndex) - baseCharCode;
    const rightChar = s.charCodeAt(rightIndex) - baseCharCode;

    if (leftChar === rightChar) {
      if (leftChar !== previousChar) {
        maxLength += 2;
      }
      maxLength += findLongestPalindrome(leftChar, leftIndex + 1, rightIndex - 1);
    } else {
      const skipLeftResult = findLongestPalindrome(previousChar, leftIndex + 1, rightIndex);
      const skipRightResult = findLongestPalindrome(previousChar, leftIndex, rightIndex - 1);
      maxLength += Math.max(skipLeftResult, skipRightResult);
    }

    return memoTable[previousChar][leftIndex][rightIndex] = maxLength;
  }
};