318. 最大单词长度乘积
给定一个字符串数组 words,找到 length(word[i]) * length(word[j]) 的最大值,并且这两个单词不含有公共字母。你可以认为每个单词只包含小写字母。如果不存在这样的两个单词,返回 0。
示例 1:
输入: ["abcw","baz","foo","bar","xtfn","abcdef"]
输出: 16
解释: 这两个单词为 “abcw”, “xtfn”。
示例 2:
输入: ["a","ab","abc","d","cd","bcd","abcd"]
输出: 4
解释: 这两个单词为 “ab”, “cd”。
示例 3:
输入: ["a","aa","aaa","aaaa"]
输出: 0
解释: 不存在这样的两个单词。
解题
基本思路: 两两比较,并判断每两个单词之间是否有公共子字符,更新最大长度;
优化1:
判断公共子字符:位运算
对每个字符串计算掩码,tmp|=1<<(ch-'a')
;得到的位为1则含有该字符;
判断两个字符串是否有公共子字符 掩码1&掩码2==0
则无公共字符;
优化2:
事先计算每个字符串的掩码,储存;
优化3:
建立map,储存 掩码:该掩码的最长字符串;
去除字符相同的短字符串;
class Solution {
public:
int maxProduct(vector<string>& words) {
//位运算 a&b==0 说明a和b没有公共字符
//预先计算每两个words的位掩码
//在unordered_map中储存位掩码-最长公共字符串
for(auto s:words){
int tmp=0;
for(auto ch:s){
tmp|=1<<(ch-'a'); //或——有一个1则就为1
}
if(map.find(tmp)==map.end()||map[tmp].length()<s.length()) map[tmp]=s;
}
int len=0;
for(auto t:map)
for(auto f:map){
if((f!=t)&&((t.first&f.first)==0))
len=len>(t.second.length()*f.second.length())?len:t.second.length()*f.second.length();
}
return len;
}
private:
unordered_map<int,string> map;
};