多个字符串的 C++ 笛卡尔积
C++ cartesian product of multiple strings
我将字符串存储在一个向量中:vector<string> ex = {"ab", "cd", "ef"}
。
现在我需要创建这些字符串的笛卡尔积(向量中字符串的数量,字符串的长度也不固定!)。结果应该是:
ace
acf
ade
adf
bce
bcf
bde
bdf
是否已经存在用于此的内置函数,或者您对如何执行实现有任何建议?
笛卡尔积应该使用字符串的单个字母而不是整个字符串!
也许结果可以用 std::accumulate 实现。
需要这种形式的二元运算
std::vector<string> product(const std::vector<string> &init, string value)
{
std::string result ;
for (auto ch : value)
if (init.empty())
result.push_back(string(1, ch)) ;
else
for (auto str : init)
result.push_back(str + string(1, ch)) ;
return result ;
}
然后调用 std::accumulate(vect.begin(), vect.end(), std::vector(), product)
好的,我想出了一个解决方案。它可能不是最好的,并且肯定可以对代码进行一些改进,但它足以满足我的目的,以防万一有人需要它:
vector<string> getProducts(vector<string> s) {
int combinations = 1;
vector<string> res;
for (unsigned int i=0; i<s.size(); i++) {
combinations *= s.at(i).length();
}
for (unsigned int i=0; i<s.size(); i++) {
string cur = s.at(i);
int div = combinations / cur.length();
int count = 0;
for (unsigned int ch=0; ch<cur.length(); ch++) {
for (int len=0; len<div; len++) {
if (i==0) {
res.push_back(string(cur.substr(ch, 1)));
} else {
string tmp = res.at(count);
tmp.append(string(cur.substr(ch,1)));
res.at(count) = tmp;
}
count++;
}
if ((ch == cur.length()-1) && (count <= res.size()-1) && i>0) {
ch = -1;
}
}
combinations = div;
}
return res;
}
我可以使用图书馆提供这种方式
https://cpplinq.codeplex.com/
#include <iostream>
#include <vector>
# include <algorithm>
# include <iterator>
# include <string>
# include <tuple>
# include <functional>
# include <cmath>
#include "cpplinq.hpp"
using namespace cpplinq;
std::vector<std::string> simpleTransform(const std::vector<std::string> &ex);
int main()
{
std::vector<std::string> ex1(3);
ex1[0]="ab";
ex1[1]="cd";
ex1[2]="ef";
auto VS = simpleTransform(ex1);
std::copy(VS.begin(),VS.end(),std::ostream_iterator<std::string>(std::cout,"\n"));
return 0;
}
std::vector<std::string> simpleTransform(const std::vector<std::string> &ex)
{
size_t N = ex.size();
size_t M = ex[0].size();
std::vector<std::string> VS(pow(M,N));
size_t count=0;
std::function<void(size_t,std::vector<size_t>)> Var=
[&](size_t ind,std::vector<size_t> vec)
{
if(ind==0)
{
std::string r;
r.resize(N);
for(size_t j=0;j<N;j++)
r[j] = ex[j][vec[j]-1];
VS[count] =r;
count++;
return;
}
else
{
std::vector<size_t> newvec(vec);
auto temp = N-ind+1;
newvec.resize(temp);
range(1,M)>>for_each([&](int const & j){
newvec[temp-1]=j;
Var(ind-1,newvec);});
}
};
Var(N,std::vector<size_t>());
return VS;
}
我没有对输入数据进行验证。
你可以使用递归。请记住,一旦遇到前一个字符串中的字符,就跳到下一个字符串。
void backtrack(int i, string cur_str, vector<string> ex, vector<string> &result)
{
//If appended string reaches the end, push to result and return;
if(cur_str.size() == ex.size())
{
result.push_back(cur_str);
return;
}
//Backtrack: Keep moving to next string recursively
for(char c : ex[i])
backtrack(i+1, cur_str+c, ex, result);
}
//Initialise a vector, result will stored here
vector<string> result;
//Call the recursive function for the first time starting at 0th index,
//and an empty string that will keep adding characters on the go
backtrack(0, "", digits, result);
您的笛卡尔积字符串的最终列表现在存储在向量中:result
我将字符串存储在一个向量中:vector<string> ex = {"ab", "cd", "ef"}
。
现在我需要创建这些字符串的笛卡尔积(向量中字符串的数量,字符串的长度也不固定!)。结果应该是:
ace
acf
ade
adf
bce
bcf
bde
bdf
是否已经存在用于此的内置函数,或者您对如何执行实现有任何建议?
笛卡尔积应该使用字符串的单个字母而不是整个字符串!
也许结果可以用 std::accumulate 实现。
需要这种形式的二元运算
std::vector<string> product(const std::vector<string> &init, string value)
{
std::string result ;
for (auto ch : value)
if (init.empty())
result.push_back(string(1, ch)) ;
else
for (auto str : init)
result.push_back(str + string(1, ch)) ;
return result ;
}
然后调用 std::accumulate(vect.begin(), vect.end(), std::vector(), product)
好的,我想出了一个解决方案。它可能不是最好的,并且肯定可以对代码进行一些改进,但它足以满足我的目的,以防万一有人需要它:
vector<string> getProducts(vector<string> s) {
int combinations = 1;
vector<string> res;
for (unsigned int i=0; i<s.size(); i++) {
combinations *= s.at(i).length();
}
for (unsigned int i=0; i<s.size(); i++) {
string cur = s.at(i);
int div = combinations / cur.length();
int count = 0;
for (unsigned int ch=0; ch<cur.length(); ch++) {
for (int len=0; len<div; len++) {
if (i==0) {
res.push_back(string(cur.substr(ch, 1)));
} else {
string tmp = res.at(count);
tmp.append(string(cur.substr(ch,1)));
res.at(count) = tmp;
}
count++;
}
if ((ch == cur.length()-1) && (count <= res.size()-1) && i>0) {
ch = -1;
}
}
combinations = div;
}
return res;
}
我可以使用图书馆提供这种方式 https://cpplinq.codeplex.com/
#include <iostream>
#include <vector>
# include <algorithm>
# include <iterator>
# include <string>
# include <tuple>
# include <functional>
# include <cmath>
#include "cpplinq.hpp"
using namespace cpplinq;
std::vector<std::string> simpleTransform(const std::vector<std::string> &ex);
int main()
{
std::vector<std::string> ex1(3);
ex1[0]="ab";
ex1[1]="cd";
ex1[2]="ef";
auto VS = simpleTransform(ex1);
std::copy(VS.begin(),VS.end(),std::ostream_iterator<std::string>(std::cout,"\n"));
return 0;
}
std::vector<std::string> simpleTransform(const std::vector<std::string> &ex)
{
size_t N = ex.size();
size_t M = ex[0].size();
std::vector<std::string> VS(pow(M,N));
size_t count=0;
std::function<void(size_t,std::vector<size_t>)> Var=
[&](size_t ind,std::vector<size_t> vec)
{
if(ind==0)
{
std::string r;
r.resize(N);
for(size_t j=0;j<N;j++)
r[j] = ex[j][vec[j]-1];
VS[count] =r;
count++;
return;
}
else
{
std::vector<size_t> newvec(vec);
auto temp = N-ind+1;
newvec.resize(temp);
range(1,M)>>for_each([&](int const & j){
newvec[temp-1]=j;
Var(ind-1,newvec);});
}
};
Var(N,std::vector<size_t>());
return VS;
}
我没有对输入数据进行验证。
你可以使用递归。请记住,一旦遇到前一个字符串中的字符,就跳到下一个字符串。
void backtrack(int i, string cur_str, vector<string> ex, vector<string> &result)
{
//If appended string reaches the end, push to result and return;
if(cur_str.size() == ex.size())
{
result.push_back(cur_str);
return;
}
//Backtrack: Keep moving to next string recursively
for(char c : ex[i])
backtrack(i+1, cur_str+c, ex, result);
}
//Initialise a vector, result will stored here
vector<string> result;
//Call the recursive function for the first time starting at 0th index,
//and an empty string that will keep adding characters on the go
backtrack(0, "", digits, result);
您的笛卡尔积字符串的最终列表现在存储在向量中:result