码迷,mamicode.com
首页 > 其他好文 > 详细

每日一题——掩码求子集

时间:2021-02-27 13:07:24      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:计算   int   blank   条件   文字   依据   列表   art   rds   

位运算基础

  • set bit: mask |= (1 << puzzle[i])
  • submask : `submask |= (submask - 1) & mask

位置掩码

https://leetcode-cn.com/problems/subsets/
先来看78题

  1. 子集
    给你一个整数数组nums ,数组中的元素互不相同。返回该数组所有可能的子集(幂集)。
    解集不能包含重复的子集。你可以按任意顺序返回解集。

思路

遍历位置掩码即可得到子集

字符集掩码

https://leetcode-cn.com/problems/number-of-valid-words-for-each-puzzle/
今日每日一题

  1. 猜字谜
    外国友人仿照中国字谜设计了一个英文版猜字谜小游戏,请你来猜猜看吧。
    字谜的迷面 puzzle 按字符串形式给出,如果一个单词 word 符合下面两个条件,那么它就可以算作谜底:
    单词 word 中包含谜面 puzzle 的第一个字母。
    单词 word 中的每一个字母都可以在谜面 puzzle 中找到。
    例如,如果字谜的谜面是 "abcdefg",那么可以作为谜底的单词有 "faced", "cabbage", 和 "baggage";而 "beefed"(不含字母 "a")以及 "based"(其中的 "s" 没有出现在谜面中)。
    返回一个答案数组 answer,数组中的每个元素 answer[i] 是在给出的单词列表 words 中可以作为字谜迷面 puzzles[i] 所对应的谜底的单词数目。

由于puzzle和word都是小写英文字符串,所以这是一个仅有26位的字符集掩码问题。

第一步:状态压缩

本质上来说虽然word和puzzle里的各字符出现次数和顺序,但判定的依据都是出现的字符的集合。
故可以压缩为字符掩码。

第二步:计算puzzle的子集

注意:计算的是不包括头部的子掩码集合

由于头部必有,所以只需要计算剩余部分的子掩码集合

for(int i = 1; i < 7; ++i)
  mask |= (1 << puzzle[i]);  //set bit

计算子掩码集合

计算子集最终要转变为子掩码,故直接计算子掩码也可。
关键代码:

submask = mask;
do{
  submask = (submask - 1) & mask;
}while(submask != mask);

这里submask = (submask - 1) & mask 之所以能够迭代submask而不重不漏,是因为submask的位模式是能够与mask按位与后产生submask的最小二进制数(听起来像句废话),所以再减去1就能得到与mask相与得到 更小的submask 的位模式。

两题的区别

字符集掩码的全集的位模式由于并不是所有位都占了,所以并不能用位置掩码(全集的位模式是所有位置都为1)那一套来计算。

每日一题——掩码求子集

标签:计算   int   blank   条件   文字   依据   列表   art   rds   

原文地址:https://www.cnblogs.com/laiyk/p/14453145.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!