打印出所有可能的固定长度的单词

时间:2014-11-13 07:41:11

标签: c++ stl permutation

我想打印出长度为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;
    }
}

但是有重复的单词。如何以最佳方式实现所需?

3 个答案:

答案 0 :(得分:1)

它在概念上与将数字从0000000 ...(n次)迭代到999999完全相同... - 只进行基数n转换:即增加一个数字,每次你想要下一个“值”,使用% n + 'a'提取“数字”和/= n以准备下一个......

答案 1 :(得分:1)

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

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

答案 2 :(得分:0)

以下可能会有所帮助:

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