<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:
        # find palindromic subSEQ of s | product of lengths is maximized
        # subseqs need to be disjoint

        # brute force: can try all possible palindromic subsequences for palindrome p1
        #              then try all longest palindromes for p2 given p1

        # all possible perms: we can skip, take p1, take p2
        #  so three choices each
        # 3**12 is too large

        # can we iterate over all palindromic subsequences?
        #   for s[0] and s[-1]: if they're the same we can wrap palindromes in 1..-2 with those two
        #   we can also find all palindromes where we discard 0 or discard -1
        # those will return a bunch of empties in the middle though

        # better idea: disjoint: find all palindromes including an index, and those not including an index

        N = len(s)

        def iterPalindromes(rem: int) -> Iterator[int]:
            """Yields bit masks of palindromes"""

            if not rem: 
                yield 0
                return

            orem = rem

            r = int.bit_length(rem)-1
            
            # palindromes where we take index r: find first l where l==r, take them, continue with the interior
            l = int.bit_length(rem & -rem)-1
            while s[l] != s[r]: 
                rem &= rem-1
                l = int.bit_length(rem & -rem) - 1
            used = (1 << r) | (1 << l) # in case they're the same
            for p in iterPalindromes(rem ^ used): yield p | used

            # palindromes where we discard index r
            for p in iterPalindromes(orem ^ (1<<r)): yield p

        # now we can solve the problem
        ALL = (1 << len(s)) - 1
        ans = 1
        for p1 in iterPalindromes(ALL):
            l1 = int.bit_count(p1)
            if l1 * (N-l1) <= ans: continue

            for p2 in iterPalindromes(ALL ^ p1):
                l2 = int.bit_count(p2)
                ans = max(ans, l1*l2)

        return ans
109