C - 生成X字符单词的所有可能性

时间:2012-02-10 19:26:26

标签: c arrays loops hash

编辑:我的意思是排列,而不是组合。感谢。

我意识到这是一个相当开放的问题,而且我不是每个人都在寻找代码,但实际上有些提示从哪里开始。我想要的是一个程序,它可以生成给定长度的每个字符组合,即用户输入4,程序将生成每个可能的ASCII字符组合,长度为4.

不确定我会从哪里开始,也许是使用哈希表?当然需要循环,但我不确定如何设计它们来生成组合。到目前为止,它始终是一个例子,循环直到1000件事情发生了。

非常感谢任何建议!

干杯,

吨。

4 个答案:

答案 0 :(得分:1)

对于排列,您可以使用这样的递归解决方案(可以对其进行优化和改进):

unordered_set<string> permute_string(int n) {    
    static const char chars[] = {
        'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
        'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
    };

    unordered_set<string> s;

    if (n == 0) {
        s.insert("");

        return s;
    }

    unordered_set<string> perms = permute_string(n - 1);

    for (auto c = std::begin(chars); c < std::end(chars); ++c)
        for (auto i = perms.begin(); i != perms.end(); ++i)
            for (int pos = 0; pos < n; ++pos)
                s.insert(string(*i).insert(pos, 1, *c));

    return s;
}

请注意,此函数的输出(无论您如何实现) 26 n n 时为456,976(这个函数的输入是4。

答案 1 :(得分:0)

你的问题太笼统了。如何,你可以使用trie数据结构来获得你想要的。但是如果你打算用c做它仍然需要很多工作。我建议使用一种语言,你不必重新创建轮子。

答案 2 :(得分:0)

是的,这几乎要求递归解决方案。要生成所有N长度的单词,基本算法是

pick the next letter from the alphabet
  generate all N-l-length words starting with that letter    

如果您需要做的就是在生成文件时将这些字符串打印到文件或其他内容,那么您不需要任何复杂的数据结构。您只需要一个缓冲区来保存生成的单词。

重要问题:您确定希望所有 ASCII字符(包括标点符号,控制字符等)的所有可能组合?或者所有可能的字母数字字符串组合?或严格的字母串?

您可能希望在代码中指定字母,例如

char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

只是索引而不是假设一个特定的字符表示:

char *p;
for (p = alphabet; *p != 0; p++)
  // generate all words starting with *p

答案 3 :(得分:0)

这是一个完整且有效的解决方案,我刚从python方法itertools.permutations的文档中转换为C ++。 http://docs.python.org/library/itertools.html#itertools.permutations。在原始的python形式中它是一个生成器(只是想迭代器)但我现在没有打扰它,虽然它会很有意义。

permutations方法是一个模板,因此这适用于您可以存储在向量中的任何对象,而不仅仅是char。使用此代码:

vector<char> alphab={'a','b','c','d'};
auto perms=permutations(alphab,3);'

结果是'vector'的向量,表示abcd的所有非重复3组合:

abc abd acb acd adb adc bac bad bca bcd bda bdc
cab cad cba cbd cda cdb dab dac dba dbc dca dcb 

这是代码(C ++ 11):

#include <vector>
#include <iostream>
#include <algorithm>

using namespace std;

size_t nperms(size_t n,size_t k){
   if(k<=0) return 1; // one empty set
   if(k>n) return 0;  // no possible ways
   size_t out=1;
   for (size_t i=n-k+1;i<=n;i++) out*=i;
   return out;
}

template<class T>
vector<T > permutations(T & iterable, size_t r=-1){    
   vector<T> out;
   T & pool = iterable;
   size_t n = pool.size();
   r = r>=0 ? r : n;
   if (r > n)
      return out;
   vector<size_t> indices;
   for (size_t i=0;i<n;++i) indices.push_back(i);
   vector<size_t> cycles;
   for (size_t i=n;i>(n-r);--i) cycles.push_back(i);

   vector<typename T::value_type> line; //e.g. vector of char
   line.reserve(r);

   for (size_t i=0;i<r;++i)
      line.push_back(pool[i]);
   out.reserve(nperms(n,r));    
   // first permutation:
   out.push_back(line);   
   while (1){
     bool done=1;
     for (size_t irev=0;irev<r;++irev){
       size_t i=r-1-irev;
       cycles[i] -= 1;
       if(cycles[i] == 0){
         // cycle upper part one step
         rotate(begin(indices)+i,begin(indices)+i+1,end(indices));
         cycles[i] = n-i;
       }else{
         int j = cycles[i];
         swap(indices[n-j],indices[i]);         
         for (size_t k=0;k<r;++k)
           line[k]=pool[indices[k]];
         out.push_back(line);
         done=0;
         break ;
       }
     }
     if(done) break;
   }
   return out;
}    
int main(){

   vector<char> alphab={'a','b','c','d'};
   auto perms=permutations(alphab,3);

   // print:
   cout <<"perms of size " <<perms.size()<<endl;
   for (auto &i : perms){
      for (auto &j : i){
     cout << j<<"";
      }
      cout <<" ";
   }
   cout <<endl;
   return 0;
}

作为说明:

字母不会被检查为唯一,而是通过索引完成排列和选择,因此如果您想要允许多个对象,只需将其添加到字母表中即可。内容也无法比较。