unordered_map仅使用16个字符串最大化唯一键

时间:2013-02-06 05:10:07

标签: c++ hash key unordered-map

此代码仅使用A,C,T,G生成随机的16个字符的字符串。然后检查此序列是否在散列(unordered_map)中,如果不是,则插入它并指向虚拟占位符。

在当前形式中,当'for i loop'需要20000次迭代时,它会挂起在datact = 16384,尽管事实上有4 ^ 16个字符串与ACTG。

但..如果字符串长度更改为8,9,10,11 ..到15或17,18 ..它正确迭代到20000.为什么unordered_map拒绝散列新序列,但仅限于那些序列长16个字符?

#include <string>
#include <vector>
#include <unordered_map>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <iostream>

using namespace std;


int main(int argc, char* argv[])
{
    string funnelstring;

    srand ( time(NULL) );

    const int buffersize=10000;
    int currentsize=buffersize;

    int datact=0;

    vector <unsigned int> ctarr(buffersize);

    vector <char> nuc(4);
    nuc[0]='A';
    nuc[1]='C';
    nuc[2]='T';
    nuc[3]='G';

    unordered_map <string,unsigned int*> location;

    unsigned int sct;
    sct=1;

    for (int i=0;i<20000; i++)
    {
        do
        {
            funnelstring="";
            for (int i=0; i<16; i++)
            {   // generate random 16 nucleotide sequence
                funnelstring+=nuc[(rand() % 4)];
            }
        } while (location.find(funnelstring) != location.end()); //asks whether this key has been assigned

        ctarr[datact]=sct;
        location[funnelstring]=&ctarr[datact]; //assign current key to point to data count
        datact++;
        cout << datact << endl;

        if (datact>=currentsize)
        {
            ctarr.resize(currentsize+buffersize);
            currentsize+=buffersize;
        }
    }

    return 0;
}

2 个答案:

答案 0 :(得分:2)

正如@ us2012所说,问题是你的PRNG,以及低阶位的差随机性。这是一个相关的引用:

  

C中的数字食谱:科学计算的艺术(William H. Press,Brian P. Flannery,Saul A. Teukolsky,William T. Vetterling; New York:Cambridge University Press,1992(2nd ed。,p。 277)),提出以下意见:

     

“如果要生成1到10之间的随机整数,则应始终使用高位来执行此操作,如

j = 1 + (int) (10.0 * (rand() / (RAND_MAX + 1.0)));
  

并且永远不会有类似的东西

j = 1 + (rand() % 10);
  

(使用低位)。“

此外,正如其他人所指出的那样,您也可以使用更好,更现代的RNG。

答案 1 :(得分:1)

罪魁祸首很可能是你的随机数生成器,即来自PRNG的随机数序列变得过于周期性(mod 4)(大多数随机数生成器真正产生 - 随机数字,因此名称PRNG)。因此,您的do...while循环永远不会退出,因为它无法找到提供随机数的新核苷酸序列。

我能想到的两个问题:

  • 不是生成随机数mod 4,而是生成它们mod 4^length并提取位对,00 -> A, 01 -> G, ...

  • 使用更好的PRNG,例如std::mersenne_twister_engine

(免责声明:我不是随机数的专家。不要依赖这个关于任务关键型系统,加密要求等的建议。)