class Solution:
  # 3503. Longest Palindrome After Substring Concatenation I
  def longestPalindrome(self, s: str, t: str) -> int:
    m = len(s)
    n = len(t)
    suffix = self._getPalindromeLengths(s, True)
    prefix = self._getPalindromeLengths(t, False)
    ans = max(max(suffix), max(prefix))
    # dp[i][j] := the longest length of palindrome starting in s[i] and ending
    # in t[j]
    dp = [[0] * n for _ in range(m)]
    for i in range(m):
      for j in range(n - 1, -1, -1):
        if s[i] == t[j]:
          dp[i][j] = 2 + (dp[i - 1][j + 1] if i > 0 and j < n - 1 else 0)
          extend = max(suffix[i + 1] if i + 1 < m else 0,
                       prefix[j - 1] if j > 0 else 0)
          ans = max(ans, dp[i][j] + extend)
    return ans
  def _getPalindromeLengths(self, s: str, isSuffix: bool) -> list[int]:
    n = len(s)
    # dp[i][j] := True if s[i..j] is a palindrome
    dp = [[False] * n for _ in range(n)]
    # lengths[i] := length of longest palindrome in s[i..n - 1]
    lengths = [0] * n
    for i in range(n - 1, -1, -1):
      for j in range(i, n):
        if s[i] == s[j] and (j - i < 2 or dp[i + 1][j - 1]):
          dp[i][j] = True
          index = i if isSuffix else j
          lengths[index] = max(lengths[index], j - i + 1)
    return lengths