重复打印选定长度字符的所有排列,并且在 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;
}

请注意,此实现远非最佳。执行时间随着每个字符添加到主排列字符串而增加阶乘时间。较大的子排列长度会大大增加内存使用,因为每个唯一排列都存储在一个集合中。但是,它确实有效,并且至少应该提供一个好的起点。