重复打印选定长度字符的所有排列,并且在 CPP 中关闭程序后不要重新开始
Print all permutations of selected length characters with repetition and do not start over after closing the program in CPP
#include <iostream>
#include <string>
using namespace std;
void enumerate(const string& s, int n, string t = "")
{
if (n == 0)
cout << t << endl;
else
{
for (char c : s)
enumerate(s, n - 1, t + c);
}
}
int main()
{
enumerate("abc", 5);
}
嗨,伙计们,我想对选定长度的字符进行所有可能的排列,但可能没电了,或者我突然关闭了程序,或者我必须重新启动计算机,所以我应该再次打开程序,然后它重新开始,这样我们的时间和精力就会浪费掉。
我也不知道这种类型的 for 循环是如何工作的 (for (char c : s)) 那么我该如何保存进度,
例如,如果循环工作了 100 次,将数字 100 保存在文本文件或其他所有内容中,之后,如果我出于某种原因关闭程序并再次打开,请从文本文件中读取数字 100,然后不要不要重新开始并继续循环。
处理字符串排列
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;
}
请注意,此实现远非最佳。执行时间随着每个字符添加到主排列字符串而增加阶乘时间。较大的子排列长度会大大增加内存使用,因为每个唯一排列都存储在一个集合中。但是,它确实有效,并且至少应该提供一个好的起点。
#include <iostream>
#include <string>
using namespace std;
void enumerate(const string& s, int n, string t = "")
{
if (n == 0)
cout << t << endl;
else
{
for (char c : s)
enumerate(s, n - 1, t + c);
}
}
int main()
{
enumerate("abc", 5);
}
嗨,伙计们,我想对选定长度的字符进行所有可能的排列,但可能没电了,或者我突然关闭了程序,或者我必须重新启动计算机,所以我应该再次打开程序,然后它重新开始,这样我们的时间和精力就会浪费掉。 我也不知道这种类型的 for 循环是如何工作的 (for (char c : s)) 那么我该如何保存进度, 例如,如果循环工作了 100 次,将数字 100 保存在文本文件或其他所有内容中,之后,如果我出于某种原因关闭程序并再次打开,请从文本文件中读取数字 100,然后不要不要重新开始并继续循环。
处理字符串排列
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;
}
请注意,此实现远非最佳。执行时间随着每个字符添加到主排列字符串而增加阶乘时间。较大的子排列长度会大大增加内存使用,因为每个唯一排列都存储在一个集合中。但是,它确实有效,并且至少应该提供一个好的起点。