<p>Given a string <code>s</code>, find two <strong>disjoint palindromic subsequences</strong> of <code>s</code> such that the <strong>product</strong> of their lengths is <strong>maximized</strong>. The two subsequences are <strong>disjoint</strong> if they do not both pick a character at the same index.</p>

<p>Return <em>the <strong>maximum</strong> possible <strong>product</strong> of the lengths of the two palindromic subsequences</em>.</p>

<p>A <strong>subsequence</strong> is a string that can be derived from another string by deleting some or no characters without changing the order of the remaining characters. A string is <strong>palindromic</strong> if it reads the same forward and backward.</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<img alt="example-1" src="https://assets.leetcode.com/uploads/2021/08/24/two-palindromic-subsequences.png" style="width: 550px; height: 124px;" />
<pre>
<strong>Input:</strong> s = &quot;leetcodecom&quot;
<strong>Output:</strong> 9
<strong>Explanation</strong>: An optimal solution is to choose &quot;ete&quot; for the 1<sup>st</sup> subsequence and &quot;cdc&quot; for the 2<sup>nd</sup> subsequence.
The product of their lengths is: 3 * 3 = 9.
</pre>

<p><strong class="example">Example 2:</strong></p>

<pre>
<strong>Input:</strong> s = &quot;bb&quot;
<strong>Output:</strong> 1
<strong>Explanation</strong>: An optimal solution is to choose &quot;b&quot; (the first character) for the 1<sup>st</sup> subsequence and &quot;b&quot; (the second character) for the 2<sup>nd</sup> subsequence.
The product of their lengths is: 1 * 1 = 1.
</pre>

<p><strong class="example">Example 3:</strong></p>

<pre>
<strong>Input:</strong> s = &quot;accbcaxxcxx&quot;
<strong>Output:</strong> 25
<strong>Explanation</strong>: An optimal solution is to choose &quot;accca&quot; for the 1<sup>st</sup> subsequence and &quot;xxcxx&quot; for the 2<sup>nd</sup> subsequence.
The product of their lengths is: 5 * 5 = 25.
</pre>

<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li><code>2 &lt;= s.length &lt;= 12</code></li>
	<li><code>s</code> consists of lowercase English letters only.</li>
</ul>

class Solution:
    def maxProduct(self, s: str) -> int:
        self.res = 0
        
        def isPalindrome(word):
            l, r = 0, len(word)-1
            while l < r:
                if word[l] != word[r]:
                    return False
                l += 1; r -= 1
            return True
        
        @functools.lru_cache(None)
        def dfs(i, word1, word2):
            if i >= len(s):
                if isPalindrome(word1) and isPalindrome(word2):
                    self.res = max(self.res, len(word1) * len(word2))
                return
            dfs(i + 1, word1, word2)
            dfs(i + 1, word1 + s[i], word2)
            dfs(i + 1, word1, word2 + s[i])
            
        dfs(0, '', '')
        return self.res
    # https://leetcode.com/problems/maximum-product-of-the-length-of-two-palindromic-subsequences/solutions/1459193/python-true-o-2-n-dp-on-subsets-solution-explained/?envType=company&envId=snowflake&favoriteSlug=snowflake-all
    # Time complexity is O(2^n), space complexity also O(2^n) to keep dp cache and last and first arrays.
    # def maxProduct(self, s: str) -> int:
    #     n = len(s)
        
    #     first, last = [0]*(1<<n), [0]*(1<<n)
        
    #     for i in range(n):
    #         for j in range(1<<i, 1<<(i+1)):
    #             first[j] = i

    #     for i in range(n):
    #         for j in range(1<<i, 1<<n, 1<<(i+1)):
    #             last[j] = i
        
    #     @lru_cache(None)
    #     def dp(m):
    #         if m & (m-1) == 0: return m != 0
    #         l, f = last[m], first[m]
    #         lb, fb = 1<<l, 1<<f
    #         return max(dp(m-lb), dp(m-fb), dp(m-lb-fb) + (s[l] == s[f]) * 2)
       
    #     ans = 0
    #     for m in range(1, 1<<n):
    #         ans = max(ans, dp(m)*dp((1<<n) - 1 - m))
            
    #     return ans
1820