题目描述:
题目分析:
题目等价于: 对于每一个 puzzle 的子集在 words 中的集合中找到合适的 word ,并求和出现的个数
1. 对于题目的要求可以看出来,总共有26个字母,所以可以用二进制来表示每一个 word 中的出现的字母的种类 (比如 "abc" : 000000...000111 来表示)
2. 然后可以用数据结构 unordered_map<int,int> 来表示每一种可能的出现的个数,这样对于每一个 puzzle 除去首字母后,进行子集枚举,求和每一个 可能 在 map 中的个数即可
子集枚举的技巧:
// 枚举子集方法一
for (int choose = 0; choose < (1 << 6); ++choose) {
// 因为必须要有首字母,所以仅对剩余 6 位进行枚举即可
int mask = 0;// 子集的表示
for (int i = 0; i < 6; ++i) {
if (choose & (1 << i)) {// 表示某位是否存在
mask |= (1 << (puzzle[i + 1] - 'a'));// 除去首字母
}
}
mask |= (1 << (puzzle[0] - 'a'));// 加上首字母
if (frequency.count(mask)) {// 判断字典中是否有该子集的可能
total += frequency[mask];
}
}
// 枚举子集方法二
int mask = 0;
for (int i = 1; i < 7; ++i) {
mask |= (1 << (puzzle[i] - 'a'));
}// mask 表示 puzzle 的后 6 位表示的集合
int subset = mask;
do {
int s = subset | (1 << (puzzle[0] - 'a'));// 算上首字母
if (frequency.count(s)) {
total += frequency[s];
}
subset = (subset - 1) & mask;// & mask 表示的是 mask 的子集
} while (subset != mask);// 因为当subset == 0 时,算上首字母仍然可以是一种情况
完整的代码段:
class Solution {
public:
vector<int> findNumOfValidWords(vector<string>& words, vector<string>& puzzles) {
unordered_map<int, int> frequency;
for (const string& word: words) {
int mask = 0;
for (char ch: word) {
mask |= (1 << (ch - 'a'));
}
if (__builtin_popcount(mask) <= 7) {
++frequency[mask];
}
}
vector<int> ans;
for (const string& puzzle: puzzles) {
int total = 0;
// 枚举子集方法一
// for (int choose = 0; choose < (1 << 6); ++choose) {
// // 因为必须要有首字母,所以仅对剩余 6 位进行枚举即可
// int mask = 0;// 子集的表示
// for (int i = 0; i < 6; ++i) {
// if (choose & (1 << i)) {// 表示某位是否存在
// mask |= (1 << (puzzle[i + 1] - 'a'));// 除去首字母
// }
// }
// mask |= (1 << (puzzle[0] - 'a'));// 加上首字母
// if (frequency.count(mask)) {// 判断字典中是否有该子集的可能
// total += frequency[mask];
// }
// }
// 枚举子集方法二
int mask = 0;
for (int i = 1; i < 7; ++i) {
mask |= (1 << (puzzle[i] - 'a'));
}// mask 表示 puzzle 的后 6 位表示的集合
int subset = mask;
do {
int s = subset | (1 << (puzzle[0] - 'a'));// 算上首字母
if (frequency.count(s)) {
total += frequency[s];
}
subset = (subset - 1) & mask;// & mask 表示的是 mask 的子集
} while (subset != 0);
ans.push_back(total);
}
return ans;
}
};