确保集合新颖性的有效方法

时间:2018-09-30 04:33:55

标签: c++ c algorithm set

给定集合N = {1,...,n},请考虑P的{​​{1}}不同的预先存在的子集。子集N的特征是0-1 S_p向量n,其中第x_p个元素是0或1,取决于第i个元素i中的项是否属于子集。让我们称这类n指标向量

例如,如果x_p,子集N={1,2,3,4,5}用向量{1,2,5}表示。

现在,给定(1,0,0,1,1)个预先存在的子集及其关联向量P

计算出由向量x_p表示的候选子集​​。

检查y是否已经是y预先存在的子集中的一部分或P确实是不属于{的一部分的新子集的最有效方法是什么{1}}个子集?

以下是我可以想到的方法:

(方法1)基本上,我们必须对所有预先存在的集合逐个元素进行检查。伪代码如下:

y

(方法2)我想到的另一种思想是存储指标向量P s的十进制等效项(此处的指标向量被视为二进制表示形式),并将其与{ {1}}。也就是说,如果for(int p = 0; p < P; p++){ //(check if x_p == y by doing an element by element comparison) int i; for(i = 0; i < n; i++){ if(x_pi != y_i){ i = 999999; } } if(i < 999999) return that y is pre-existing } return that y is new 个预先存在的集合的集合为:x_p,则该集合的存储小数将为y。如果P{ (0,1,0,0,1), (1,0,1,1,0) },我们计算{9, 22}并对照集合y进行检查。这种方法的好处是,对于每个新的(0,1,1,0,0),我们不必对照每个预先存在的集合的12元素进行检查。我们可以比较十进制数。

问题1.在我看来(方法2)应该比(方法1)更有效。对于(方法2),是否有一种有效的方法(C / C ++中的内置库函数)将{9, 22}y从二进制转换为十进制?这些指标变量的数据类型应该是什么?例如nx_p

问题2.是否有比(方法2)更有效的方法?

2 个答案:

答案 0 :(得分:1)

正如您所注意到的,指标向量和N位整数之间有一个琐碎的同构。这意味着问题2的答案为“否”:用于维护集合和测试集合中成员资格的工具与整数相同(哈希表采用常规方法)。有评论提到,Bloom填充器可以有效地测试成员资格,但存在误报的风险,但Bloom过滤器通常用于比您要查看的数据大得多的数据。

关于您的问题1:方法2是合理的,甚至比您想象的要容易。尽管vector<bool>并没有为您提供将其转换为整数块的简便方法,但在实现方面,我知道它已经以这种方式实现(C ++标准允许对该特定矢量类型进行特殊处理,这通常是如今被认为是一个错误的决定,但偶尔会带来一些好处)。这些向量是可哈希的。因此,只需保持unordered_set<vector<bool>>,您将获得可以合理地接近最佳性能的性能。 (如果您在编译时知道N,则可能更喜欢bitset而不是vector<bool>。)

答案 1 :(得分:-1)

方法2可以通过计算给定子集的十进制等效值并使用模数1e9 + 7对其进行散列来进行优化。由于N <= 1000(不会发生碰撞),因此每次生成的十进制数都不同。

#define M 1000000007  //big prime number
unordered_set<long long> subset;  //containing decimal representation of all the 
                                  //previous found subsets

/*fast computation of power of 2*/
long long Pow(long long num,long long pow){
    long long result=1;
    while(pow)
    {
        if(pow&1)
        {
            result*=num;
            result%=M;
        }
        num*=num;
        num%=M;
        pow>>=1;
    }
    return result;
}
/*checks if subset pre exists*/
bool check(vector<bool> booleanVector){
    long long result=0;
    for(int i=0;i<booleanVector.size();i++)
        if(booleanVector[i])
            result+=Pow(2,i);
    return (subset.find(result)==subset.end());
}