【问题标题】:Sequential Key Generation顺序密钥生成
【发布时间】:2011-01-05 06:18:51
【问题描述】:

现在,我正在开发一个需要顺序生成文本密钥的项目。我需要使用与某个键对应的整数为键生成器播种,构造函数将其转换为键。

我的键生成器重载了增量运算符,因此字符串直接递增,而不是我之前所做的,即递增索引值,然后将索引转换为我想要生成的每个键的键。

我的问题是,我想在生成密钥时使用有限的字符集。我必须找到要递增的键中的字符,找出它在我的字符集中的位置,找到集中的下一个字符,然后用集中的下一个字符替换键中的字符。

这是我的代码:

// Not the full charset
std::string charset = "abcdefghijklmnopqrstuvwxyz0123456789"; 
std::string key;

key.push_back(charset[0]);

for(unsigned int place = 0; place < key.length(); place++)
{
    if(key[place] == charset[charset.length() - 1])
    {
        // Overflow, reset char at place
        key[place] = charset[0];

        if((key.length() - 1) < (place + 1))
        {
            // Carry, no space, insert char
            key.insert(key.begin(), charset[0]);
            break;
        }
        else
        {
            // Space available, increment next char
            continue;
        }
    }
    else
    {
        // Increment char at place
        key[place] = charset[charset.find(key[place]) + 1];
        break;
    }
}

在分析中,我发现搜索操作确实让事情变慢了。有没有更快的方法来做到这一点?我想从字符集创建一个链接列表,但在我这样做之前,我想对此进行一些输入。

【问题讨论】:

  • 为什么不使用 GUID?
  • 搜索链表会比搜索字符串更快吗?

标签: c++ string increment


【解决方案1】:

与其做一个查找,你为什么没有一个反向翻译数组?数组索引是字符,数组中的值是它的数值(或另一个数组的索引)。

key[place] = charset[reverse_charset[key[place]] + 1];

【讨论】:

  • 这比不翻译有什么好处?
  • 回答自我:不需要修改算法。虽然我认为算法首先是错误的。
  • 另外:不是我的反对意见。这个答案没有错,也是最简单的。
  • 原始算法的优点是它不需要任何信息,除了最后分发的密钥。当然,这不是一个引人注目的优势。
【解决方案2】:

您可以存储与键长度相同的向量,其中向量中的每个元素都是键中相应字符的字符集中的索引。

例如,如果 key[0] 是“c”,那么 thisVector[0] 将是 2,因为“c”是字符集中的第三个字符。

然后所有操作都将在该整数向量上执行,从而消除了对字符串进行find 操作的必要性。

【讨论】:

    【解决方案3】:

    也许您最好将索引处理到字符集中,然后在需要时将它们转换为实际字符?

    这将节省您在字符集中搜索字符的开销。并且将字符集索引转换为字符将是一个常数时间操作,与逆操作不同。

    将您的密钥存储为整数 0 ~ N-1 的向量,其中 N 是您的字符集的长度。仅在需要时(即在增量之后)将这些整数转换为实际字符。

    【讨论】:

      【解决方案4】:

      这是广义基转换问题的另一个版本,n=36。

      您想要做的是将您的密钥视为一个无符号整数,并将您分发的“字符串”视为该密钥的基数 36 (a-z + 0-9) 表示形式。

      分发一个键然后将“下一个键”值转换为 base36 字符串,然后递增下一个键值。

      要进行转换,请执行与将任何整数转换为十六进制表示相同的操作,但在模数数学中交换 36 而不是 16。我将把它作为练习留给读者。 :)

      【讨论】:

      • 这实际上是我正在做的,但由于它执行大量的 64 位算术,它比我现在的慢五倍。
      • 我很难相信;现代处理器真的很擅长算术,而且没有那么多事情可做。我想看看这个版本的代码并尝试优化它。十六进制转换算法按照我建议的方式而不是您尝试的方式是有原因的。
      • pastebin.com/m793cd41b 就像我说的,我正在处理非常大的 64 位整数,它需要大量的算术才能转换为另一个基数。运行 32 位构建时,性能更差,因为 64 位算法必须在软件中完成。
      【解决方案5】:

      我不确定我是否完全理解您想要做什么,但这里有一个小控制台程序,它使用您的字符集作为数字打印出以 36 为基数的 36*36*36 3 位键序列。所以它从 aaa 开始,到 999 结束。

      #include <stdio.h>
      typedef int Number;
      const size_t N = 3;
      size_t B = 36;
      Number key[N] = {0};
      bool carry = false;
      char A[] = "abcdefghifjlmnopqrstuvwxyz0123456789";
      
      void incr(size_t i)
      {
          if(!carry)
          {
              return;
          }
          ++key[i];
          if(key[i] == B)
          {
              key[i] = 0;
          }
          else
          {
              carry = false;
          }
      }
      
      void Incr()
      {
          carry = true;
          size_t i = 0;
          while(carry)
          {
              incr(i++);
          }
      }
      
      void Print()
      {
          for(int i = N - 1; i >= 0; --i)
          {
              printf("%c", A[key[i]]);
          }
          printf("\n");
      }
      
      int _tmain(int argc, _TCHAR* argv[])
      {
          for(int i = 0; i < B * B * B; ++i)
          {
              Print();
              Incr();
      
          }
          return 0;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-01-10
        • 2015-04-01
        • 2013-02-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-17
        相关资源
        最近更新 更多