Another O(n^2) solution using bit ops. We prune 1/2(expected) candidates at each bit check.
#define MAX_BITS 1600typedef bitsetCandMask;class Solution { // string to char bit mask uint32_t w2m(const string &s) { uint32_t ret = 0; for (auto c : s) ret |= 1 << (c - 'a'); return ret; }public: int maxProduct(vector & words) { int n = words.size(); // Calculate masks of each word vector wmasks; for (auto &s : words) wmasks.push_back(w2m(s)); // Categorize words by each bit on\off vector > recs(26, vector (2)); for (int i = 0; i < n; i++) for (int b = 0; b < 26; b++) { if (wmasks[i] & (1 << b)) recs[b][1][i] = 1; else recs[b][0][i] = 1; } // CandMask OrigCandMask; for (int k = 0; k < wmasks.size(); k++) OrigCandMask[k] = 1; int ret = 0; for (int i = 0; i < n; i++) { uint32_t m = wmasks[i]; int len1 = words[i].length(); // Binary search by bits CandMask candidates = OrigCandMask; for (int b = 0; b < 26; b++) if (m & (1 << b)) candidates &= (~recs[b][1]); for (int k = 0; k < min(n, MAX_BITS); k++) if (candidates[k]) ret = max(ret, len1 * int(words[k].length())); } return ret; }};