C++ 中有趣的位掩码谜题

Posted

技术标签:

【中文标题】C++ 中有趣的位掩码谜题【英文标题】:Interesting bitmask puzzle in C++ 【发布时间】:2012-05-05 11:01:51 【问题描述】:

我有一个有趣的位掩码难题,我需要帮助解决一些问题。问题来了:

11010

每个位代表一段内容的一个特征。它存储在 Redis 中。但是要查询它,我们需要每个组合,以便我们可以拉出密钥。所以11010 会产生这些组合:

11010
10000
10010
11000
01010
00010
01000

有人有 C++ 的解决方案吗?

【问题讨论】:

所以基本上你需要类似if (search_key & item_key) != 0) ...的东西? 如何在 n^2 中解决?你是说 2^n 吗? 您是否在问如何在不到 2^n 的时间内生成最多 2^n 个值的列表?认真的吗? 似乎是集合问题的所有子集。这是一个指数算法! 啊,看,所以我们需要做的就是确保 n 足够小。然后 2^n 击败 n^2。问题解决了。 【参考方案1】:

请参阅Chess Programming Wiki,了解初始位掩码的子集数量呈线性关系的算法。将 n 位设置为 1 时,该数字等于 2^n,因此它是设置位数的指数。

// enumerate all subsets of set d
void enumerateAllSubsets(U64 d) 
   U64 n = 0;
   do 
      doSomeThingWithSubset(n);
      n = (n - d) & d;
    while ( n );

【讨论】:

谢谢,太好了!我会阅读这个。感谢大家的帮助!【参考方案2】:

如果 2^n (n=bits set) 大于您拥有的键数,则可能会更快地解决问题。也就是说,获取您的键列表并根据位掩码测试它们,而不是枚举可能的键并检查值。

【讨论】:

以上是关于C++ 中有趣的位掩码谜题的主要内容,如果未能解决你的问题,请参考以下文章

Postgres 中的位掩码

以下程序中的位掩码用法来自 Programming Pearls

使用 SQLite 进行位掩码分组

位掩码:如何确定是不是只设置了一位

有效地找到匹配位掩码的第一个元素

选择位掩码中与选择器位图中的 1 位重叠的设置位范围