我必须从“az”,“AZ”和“0-9”中随机生成大集(10k甚至更多)字符串,其大小为32个字符。 。
到目前为止,我的脑海中有以下代码(O(N * 32)),但我想知道是否有更好的方法可以做到这一点。
int N = 10000;
vector<string> vecStr;
for (int index=0; index<N; index++)
{
string str;
for (int i = 0; i < 32; ++i)
{
int randomChar = rand()%(26+26+10);
if (randomChar < 26)
str += 'a' + randomChar;
else if (randomChar < 26+26)
str += 'A' + randomChar - 26;
else
str += '0' + randomChar - 26 - 26;
}
vecStr.push_back(str);
}
答案 0 :(得分:6)
你不会找到比O(N * len)更好的解决方案,其中N是字符串的数量,len是其中每个的长度。也就是说,在某些地方,我确信我可以通过编写最密集的代码来获得失去光泽的贴纸:
#include <iostream>
#include <iterator>
#include <vector>
#include <random>
#include <algorithm>
int main()
{
static const char alphabet[] =
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789";
static const size_t N_STRS = 10000;
static const size_t S_LEN = 32;
std::random_device rd;
std::default_random_engine rng(rd());
std::uniform_int_distribution<> dist(0,sizeof(alphabet)/sizeof(*alphabet)-2);
std::vector<std::string> strs;
strs.reserve(N_STRS);
std::generate_n(std::back_inserter(strs), strs.capacity(),
[&] { std::string str;
str.reserve(S_LEN);
std::generate_n(std::back_inserter(str), S_LEN,
[&]() { return alphabet[dist(rng)];});
return str; });
std::copy(strs.begin(), strs.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
return 0;
}
输出(为简洁省略了9990行= P)
MRdeOWckfKy8GTFt0YmQMcM6SABJc934
XvdcatVsv6N9c1PzQGFFY6ZP943yIrUY
xpHzxUUyAizB6BfKldQzoePrm82PF1bn
kMUyPbflxk3yj3IToTFqYWnDq6aznKas
Ey0W5SF37VaeEY6PxWsBoxlNZTv9lOUn
iTx7jFRTHHW6TfYl7N3Hne4yu7kgAzp5
0ZamlaopjLyEvJbr6fzJPdXmjLOohtKh
6ZYeqj47nCMYKj0sCGl2IHm28FmvuH8h
oTDYRIA1trN1A2pQjsBwG3j9llzKIMhw
5zlpvSgTeLQ38eFWeSDoSY9IHEMHyzix
请注意,您可能会惊讶地发现它的速度有多快。引擎盖下发生了很多事情。最后,这使用了C ++ 11随机库,特别是均匀分布,消除了传统rand() % n
解决方案对特定n
通常遇到的模偏差。
答案 1 :(得分:2)
您可能会考虑C ++ 11中提供的random number generators and distributions。
如,
const char alphanumeric[] = "0 .. 1A .. Za.. z";
std::default_random_engine rng;
std::uniform_int_distribution<> dist (0, sizeof(alphanumeric) - 1);
...
for (int i = 0; i < 32; i++)
str += alphanumeric[dist(rng)];
我添加vecStr.push_back(str)
可能不会那么昂贵,因为它可能会使用std::string
对象的移动分配。 std::string
对象在其实现中通常也有“短字符串”优化(SSO)。
vector<string> vecStr (N);
...
vecStr[index] = std::move(str);
答案 2 :(得分:1)
你不能做得比O(mn)
更好(其中m
是字符串的长度(此处为= 32),n
是字符串的数量。)
原因是输出大小为O(mn)
,逻辑上需要至少O(1)
对输出中的每个字符起作用。
请注意,您的算法可能比O(mn)
慢一些,因为字符串的某些重新分配可能会发生。为防止这种情况,您可以使用string::reserve
:
int M = 32;
...
string str;
str.reserve(M);
for (int i = 0; i < M; ++i)
...
但鉴于M
只有32,它不太可能产生显着差异。
而且,只是为了好玩,以下是您的代码的变体:
int N = 10000, M = 32;
vector<string> vecStr;
string alphabet("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
for (int index = 0; index < N; index++)
{
string str;
str.reserve(M);
for (int i = 0; i < M; ++i)
{
str += alphabet[rand() % alphabet.length()];
}
vecStr.push_back(str);
}
答案 3 :(得分:0)
考虑为随机字符串使用预分配缓冲区。 此外,您可能会预生成一些随机块并置换它们。
答案 4 :(得分:0)
在算法效率方面没有太大改进,但我建议
void random_string(char *s, int len=32) {
static const char alphabet[] =
"0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
for (int i = 0; i < len; ++i) {
s[i] = alphabet[rand() % (sizeof(alphabet) - 1)];
}
s[len] = '\0';
}