【问题标题】:Print out all possible fixed length words打印出所有可能的固定长度单词
【发布时间】:2014-11-13 07:41:10
【问题描述】:

我想打印出长度为n 的所有可能的单词(为测试其他算法生成输入),其中包含从'a''a' + n 的(可能重复的)字母。

我尝试执行以下操作:

#include <iostream>
#include <string>
#include <algorithm>

using size_type = std::size_t;
using symbol_type = std::string;
using char_type = typename symbol_type::value_type;

template< size_type n >
struct test
{

    static_assert(!(size_type('z' - 'a') + 1 < n));

    void
    print(symbol_type const & _symbol) const
    {
        for (size_type i = 0; i < n; ++i) {
            std::cout << _symbol.substr(i * n, n) << std::endl;
        }
        std::cout << std::endl;
    }

    bool
    operator () () const
    {
        symbol_type mishmash_;
        for (size_type i = 0; i < n; ++i) {
            mishmash_.append(symbol_type(n, char_type('a' + i)));
        }
        print(mishmash_);
        while (std::next_permutation(std::begin(mishmash_), std::end(mishmash_))) {
            print(mishmash_);
        }
        return true;
    }

};

int
main()
{
    test< 3 > const test_{};
    if (test_()) {
        std::cout << "Succes!" << std::endl;
        return EXIT_SUCCESS;
    } else {
        std::cerr << "Failure!" << std::endl;
        return EXIT_FAILURE;
    }
}

但是有重复的单词。如何以最优化的方式实现期望?

【问题讨论】:

  • 您不需要next_permutation,因为您已经说过字母可能重复。
  • @MohitJain 我确定我需要类似于next_permutation 的东西,STL 中没有类似的功能(在某种意义上除了random_suffle)。如您所见,我打印出整个字符串(长度为 n * n)的子字符串(长度 = n),其中包含每个字母的 n 重复项。
  • 您正在创建字符串 aaabbbccc 并打印其排列的前 3 个字符。当前 3 个字符相同但其余字符重复时,您无法区分字符串。所以在这里你可以在没有 STL 的情况下工作得更好。 (例如递归和回溯)
  • 可以通过n嵌套for循环来实现。
  • 您也可以使用 1 for 循环来实现它。或者使用std::set 来跟踪已经打印的组合,不要再打印了。

标签: c++ stl permutation


【解决方案1】:

从概念上讲,这与将数字从 0000000...(n 次)迭代到 999999... 的任务相同 - 只需进行 base-n 转换:即递增一个数字,每次您想要下一个“值”时,使用% n + 'a' 提取“数字”并使用/= n 准备获取下一个....

【讨论】:

    【解决方案2】:

    您可以编写如下所示的测试类。

    struct test
    {
    
        //static_assert(!(size_type('z' - 'a') + 1 < n));
    
        void
        print(symbol_type const & _symbol) const
        {
            std::cout << _symbol << std::endl;
        }
    
        bool
        operator () () const
        {
            symbol_type mishmash_(n, char_type('a' - 1));
            int cidx = 0;
            while (cidx >= 0) {
                if(cidx == n) {
                    print(mishmash_);
                    --cidx;
                } else {
                    if(++mishmash_[cidx] == char_type('a' + n)) --cidx;
                    else mishmash_[++cidx] = char_type('a' - 1);
                }
            }
            return true;
        }
    };
    

    Live example here

    【讨论】:

      【解决方案3】:

      以下可能会有所帮助:

      template <typename T>
      bool increase(const std::vector<T>& v, std::vector<std::size_t>& its)
      {
          for (std::size_t i = 0, size = its.size(); i != size; ++i) {
              const std::size_t index = size - 1 - i;
              ++its[index];
              if (its[index] == v.size()) {
                  its[index] = 0;
              } else {
                  return true;
              }
          }
          return false;
      }
      
      template <typename T>
      void do_job(const std::vector<T>& v, std::vector<std::size_t>& its)
      {
          // Print example.
          for (std::size_t i = 0, size = v.size(); i != size; ++i) {
              std::cout << v[its[i]] << " ";
          }
          std::cout << std::endl;
      }
      
      template <std::size_t N>
      void test()
      {
          std::vector<char> v(N);
          std::iota(v.begin(), v.end(), 'a');
          std::vector<std::size_t> its(N, 0);
      
          do {
              do_job(v, its);
          } while (increase(v, its));
      
      }
      

      Live example.

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-09-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-16
        • 1970-01-01
        • 2021-12-14
        相关资源
        最近更新 更多