Печатать все перестановки символов выбранной длины с повторением и не начинать заново после закрытия программы в 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 из текстового файла и не делайте этого. t начать заново и продолжить цикл.

Проверьте, что n < s.length() в вашей enumerate() функции.

πάντα ῥεῖ 11.12.2020 23:30

Кажется, вы хотите декартово произведение, а не перестановку.

Jarod42 11.12.2020 23:40

Какой вопрос?

Jarod42 11.12.2020 23:40
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
3
189
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Обработка перестановок строк

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;
}

Обратите внимание, что эта реализация далека от оптимальной. Выполнение увеличивается на факториальное время с каждым символом, добавляемым в основную строку перестановки. Большая длина дочерней перестановки значительно увеличивает использование памяти, поскольку каждая уникальная перестановка хранится в наборе. Тем не менее, это работает и должно стать как минимум хорошей отправной точкой.

Спасибо за ваш полный ответ и реальное объяснение, но есть небольшая проблема: в строке 18 команда .contains неверна. Я пробовал MinGW С++ 11 и компилятор VS, но это не сработало.

Aschkan 12.12.2020 10:59

Ах да, извините. .contains является частью C++ 20. Замените условное выражение на childPermsTried.emplace(childPermutation) == childPermsTried.end(), и оно будет работать с C++ 11. Вызов insert в строке 19 также необходимо изменить на emplace, потому что вставка является частью C++ 17.

scupit 12.12.2020 19:59

Другие вопросы по теме