通过在每个位置从特定位置的单词池中选择单词,有效地生成所有序列
Efficiently generating all sequences by selecting word from position specific word pool at each position
我有一个类似的特定序列;
x y a
x could represent two words "Xerox" and "Copy".
y could represent three words "china", "DRC" and "Chinese".
a could represent two words "jinx" and "omen"
该序列最多可以由6个单词组成。我有一个从每个项目到向量容器中它的等价字符串的映射。因此,主要目标是通过使用每个项目的不同选项来获得所有可能的单词组合。例如,对于上述情况,所有可能的输出都是。。。
Xerox china jinx
Xerox china omen
Xerox DRC jinx
Xerox DRC omen
Xerox Chinese jinx
Xerox Chinese omen
Copy china jinx
Copy china omen
Copy DRC jinx
Copy DRC omen
Copy Chinese jinx
Copy Chinese omen
目前我正在考虑递归实现,但我无法在我的解决方案中清楚地表达这个想法。我将感谢你的建议和想法。
谢谢。
您实际上并不需要任何递归。
可以列举这样的所有可能性:
- x的索引可以是零或一
- y的索引可以是0、1或2
- a的索引可以是零,也可以是一
通常情况下,您只想在溢出时递增下一个bin,并在最后一个bin溢出时终止循环。想象一下,如果你只有两个选项,每个选项都有一个二进制计数器,你会不断递增,计数器中的每一位都会选择第一个或第二个单词。这也没什么不同。
算法看起来像这样:
Initialize num_lists to number of word lists.
Initialize word lists per position.
Initialize max_count array for the number of words per position.
Initialize count array to all zeros.
Repeat
Print words corresponding to count array (count_array[0] select first word etc.)
Carry = 1 // We're basically adding 1 to our counter
Index = 0
While Carry and Index<num_lists
Add Carry to count[Index]
If count[Index]==max_count[Index] then Carry=1; max_count[Index] = 0
Else Carry = 0
Index = Index + 1
End
While Carry==0
如果您希望代码可读,我认为递归解决方案是一个很好的方法。如果你可以有太多的维度,你显然有栈溢出的风险,但除此之外,我个人更喜欢递归。
下面的代码假设您有一个二维字符串数组,表示为vector < vector<string> >
,我称之为v
。
关键是要跟踪每个维度的索引。我使用一个int数组来实现这一点。假设我知道从每组字符串中我想要哪个字符串,那么很容易打印出来:
void printSequence(const vector< vector<string> > &v, const vector<int> &indices) {
int n = indices.size();
for (int i = 0; i < n; i++) {
cout << v[i][indices[i]];
if (i < n - 1) {
cout << " ";
} else {
cout << endl;
}
}
}
递归调用是构造这样一个数组的简单方法。这里的d
代表尺寸。在每个递归级别,我们用一个插入d
的元素来填充indices
数组。当我们有了所有这些,我们就可以把它们打印出来。
void print(const vector< vector<string> > &v, vector<int> &indices, int d) {
int n = v.size();
if (d == n) {
printSequence(v, indices);
return;
}
for (int i = 0; i < v[d].size(); i++) {
indices.push_back(i);
print(v, indices, d + 1);
indices.pop_back();
}
}
如果你想一想你的例子,最后使用的索引数组会是这样的:
- 0,0,0
- 0,0,1
- 0,1,0
- 0,1,1
- 0,2,0
- 0,2,1
- 1,0,0
- 1、2、1
假设您已经填充了v,您可以这样调用print
:
vector<int> indices;
print(v, indices, 0);
您的问题只是向量x × (y × (a × ...))
的笛卡尔乘积,因此以这种方式进行编码可能是直观的。
递归是个好主意,因为问题本质上是递归的。它是foldr
,这是一种常见的函数模式,但需要一个初始值(在本例中,是一个带有空字符串的向量)
vector<string> cartesian_concat(const vector<string>& a,
const vector<string>& b) {
vector<string> result;
for (const string& i : a)
for (const string& j : b)
result.push_back(i + " " + j);
return result;
}
template <typename T, typename U>
U vec_foldr(U (*f)(const T&, const U&),
const U& init,
const vector<T>& l,
unsigned pos=0) {
if (pos < l.size())
return f(l.at(pos), vec_foldr(f, init, l, pos+1));
return init;
}
vector<vector<string>> m {
{ "Xerox", "Copy" },
{ "china", "DRC", "Chinese" },
{ "jinx", "omen" }};
for (const string& i : vec_foldr(cartesian_concat, { "" }, m))
cout << i << endl;
void print(vector<vector<string> >& var, vector<string>& to_print, int level)
{
if(level == var.size() - 1)
{
for(int i = 0; i < var[level].size(); ++i)
{
std::copy(to_print.begin(), to_print.end(),
ostream_iterator<string>(cout, ","));
cout << var[level][i] << endl;
}
return;
}
for(int i = 0; i < var[level].size(); ++i)
{
to_print.push_back(var[level][i]);
print(var, to_print, level + 1);
to_print.pop_back();
}
}
int main(int argc, const char * argv[])
{
vector<vector<string> > var;
string X[] = { "Xerorx", "Copy"};
string Y[] = { "china", "DRC", "chinease"};
string Z[] = { "jinx", "omen"};
var.push_back(vector<string>(X, X + 2));
var.push_back(vector<string>(Y, Y + 3));
var.push_back(vector<string>(Z, Z + 2));
vector<string> to_print;
print(var, to_print, 0);
}
- 有效地使用std::unordered_map来插入或增加键的值
- 如何有效地在 std::vector 中插入一对?
- 有效地计算多维数组的累积和?
- 如何有效地计算将单位立方体映射到自身的反射和旋转?
- 有效地将大数存储为 2 的幂用于路径问题
- 如何在C++中写入 1000 个文件时有效地缓冲
- 如何有效地找到数组中三元组和的最小差异?
- 如何在C++中有效地将数字值重新分配给字符数组
- C++有效地找到向量中第一个最接近的匹配值?
- 如何有效地操作满足给定谓词的向量中的所有项目?
- 有效地将数据加载到 std::vector 中<char>
- 如何在使用 cin 请求 int 时有效地使用户输入万无一失?
- C++:有效地将Sha256摘要放入OpenSSL Bignum?
- 如何有效地收集给定数组中的重复元素?
- 如何有效地修剪和合并四叉树中的节点?
- 可以有效地转换 std::any 与 std::any_cast
- 只需要知道我在c ++中打印模式的方式是否有效,或者有另一种方法可以有效地做到这一点
- 如何使用包含内部类的类实例有效地从内部类访问成员?
- 通过在每个位置从特定位置的单词池中选择单词,有效地生成所有序列
- 在代码中的同一位置最有效地填充静态标题列表和动态值列表