Given that you want both AAB
and ABA
to be output, you are looking for permutations rather than combinations. In particular, you are looking for the unique permutations of a set of size k where the elements are drawn with replacement from a set of n tokens. The number of combinations is n+k-1Ck while the number of permutations is nk.
说明这两个概念的伪代码:
build_combinations (tokens, set_size)
Arrangements combos
if (set_size == 0)
combos.add ("")
else
Comment: tail_substrings of "ABC" is ("ABC", "BC", "C").
foreach tail (tail_substrings (tokens))
foreach sub_combo (build_combinations (tail, set_size-1))
combos.add (tail.first() + sub_combo)
return combos
build_permutations (tokens, set_size)
Arrangements perms
if (set_size == 0)
perms.add ("")
else
sub_perms = build_permutations (tokens, set_size-1)
foreach token (tokens)
foreach perm (sub_perms)
perms.add (cur_token + *rem_iter)
return perms
一个有效的 C++ 实现:
#include <string>
#include <vector>
typedef std::string::const_iterator StringIterator;
typedef std::vector<std::string> Arrangements;
typedef Arrangements::const_iterator ArrangementsIterator;
Arrangements build_combinations (const std::string & tokens, unsigned set_size)
{
Arrangements combos;
if (set_size == 0) {
combos.push_back ("");
}
else {
for (StringIterator token_iter = tokens.begin();
token_iter != tokens.end();
++token_iter) {
std::string cur_token(1, *token_iter);
std::string rem_tokens(token_iter, tokens.end());
Arrangements rem_combos = build_combinations (rem_tokens, set_size-1);
for (ArrangementsIterator rem_iter = rem_combos.begin();
rem_iter != rem_combos.end();
++rem_iter) {
combos.push_back (cur_token + *rem_iter);
}
}
}
return combos;
}
Arrangements build_permutations (const std::string & tokens, unsigned set_size)
{
Arrangements perms;
if (set_size == 0) {
perms.push_back ("");
}
else {
Arrangements rem_perms = build_permutations (tokens, set_size-1);
for (StringIterator token_iter = tokens.begin();
token_iter != tokens.end();
++token_iter) {
std::string cur_token(1, *token_iter);
for (ArrangementsIterator rem_iter = rem_perms.begin();
rem_iter != rem_perms.end();
++rem_iter) {
perms.push_back (cur_token + *rem_iter);
}
}
}
return perms;
}