C++ Bitmask DP Time: O(n * 3^n), Space: O(2^n)
dp[mask]represent the maximum length of palindrome if we used these characters.\nThere are two cases:\n1) If mask represent a palindrome subsequence, dp[mask]= 
```dp[mask]```represent the maximum length of palindrome if we used these characters.\nThere are two cases:\n1) If mask represent a palindrome subsequence, ```dp[mask]```= the length of that subsequence.\n2) If mask is not a palindrome subsequence, we iterate through all its submasks and find the longest palindrome length\n\nFinally, we iterate through all masks and find the maximum product of ```dp[mask]``` and ```dp[~mask]```, which sums up to the whole string.\n```\nbool ispalin(const string& s) {\n    int l = 0, r = s.size() - 1;\n    while(l < r) {\n        if(s[l] != s[r])\n            return false;\n        ++l, --r;\n    }\n    return true;\n}\n\nclass Solution {\npublic:\n    int maxProduct(string s) {\n        const int N = s.size();\n        vector<int> dp(1 << N);\n        for(int mask = 1; mask < (1 << N); ++mask) {\n            string cur;\n            for(int i = 0; i < N; ++i)\n                if(mask & (1 << i))\n                    cur += s[i];\n            if(ispalin(cur))\n                dp[mask] = cur.size();\n            else {\n                for(int sub = mask; sub; sub = (sub - 1) & mask)\n                    dp[mask] = max(dp[mask], dp[sub]);\n            }\n        }\n        int ans = 0;\n        for(int mask = 0; mask < (1 << N); ++mask) {\n            int a = dp[mask];\n            int other = 0;\n            for(int i = 0; i < N; ++i)\n                if(!(mask & (1 << i)))\n                    other |= 1 << i;\n            int b = dp[other];\n            ans = max(ans, a * b);\n        }\n        return ans;\n    }\n};\n```
['Dynamic Programming', 'C', 'Bitmask']