处理字符串排列
C++ 有一个方便的标准库算法std::next_permutation,您可以使用它来为您处理字符串排列。
一个解决方案
下面是一种蛮力方法,其中对较大的“父”字符串的每个可能的排列进行迭代,并测试第一个 n 字符子字符串的唯一性。如果该子子字符串是唯一的,则将其打印并添加到“已使用”子排列集合中。
每次迭代后,您都可以保存当前的父排列状态。您可以稍后将其传递给print_permutation 函数,该函数将从该点恢复排列计算。有关详细信息,请参阅下面的实现。
#include <algorithm>
#include <functional>
#include <iostream>
#include <string>
#include <unordered_set>
typedef std::function<void(const std::string& masterPerm, const bool finished)> PermutationCallback;
std::string new_master_permutation(std::string&& str) {
std::sort(str.begin(), str.end());
return str;
}
void print_permutation_if_unused(
const std::string& childPermutation,
std::unordered_set<std::string>& childPermsTried
) {
if (!childPermsTried.contains(childPermutation)) {
childPermsTried.insert(childPermutation);
std::cout << childPermutation << '\n';
}
}
void print_permutations(
std::string masterPermutation,
const size_t numCharsInPerm,
const PermutationCallback& callback
) {
std::unordered_set<std::string> childPermsTried;
// Actual constrained length of child permutation strings
const size_t permutationLength = std::min(masterPermutation.size(), numCharsInPerm);
do {
print_permutation_if_unused(masterPermutation.substr(0, permutationLength), childPermsTried);
callback(masterPermutation, false);
} while (std::next_permutation(masterPermutation.begin(), masterPermutation.end()));
callback(masterPermutation, true);
}
int main(void) {
// Begin with a new permutation, starting with the sorted string "abbc"
print_permutations(new_master_permutation("bacb"), 3,
[](const std::string& masterPerm, const bool finished) {
// Save the master permutation for reference
}
);
// Begin at any midpoint permutation ("bacb"), and calculate the rest.
print_permutations("bacb", 3, [](const std::string& masterPerm, const bool finished) {
// Save the master permutation for reference
});
return EXIT_SUCCESS;
}
请注意,此实现远非最佳。随着每个字符添加到主排列字符串,执行时间会增加。较大的子排列长度会大大增加内存使用,因为每个唯一排列都存储在一个集合中。但是,它确实有效,并且至少应该提供一个良好的起点。