Вот альтернативное решение. Это не ожидает, что вы передадите ничего, кроме начальных векторов:
int resultSize( vector< vector<string> > vector ){
int x=1;
for( int i=0;i<vector.size(); i++ )
x *= vector[i].size();
return x;
}
vector<string> enumAll(const vector< vector<string> > allVecs )
{
//__ASSERT( allVecs.size() > 0 );
vector<string> result;
if( allVecs.size() == 1 ){
for( int i=0 ; i< allVecs[0].size(); i++){
result.push_back( allVecs[0][i] );
}
return result;
}
for( int i=0; i<allVecs[0].size(); i++ ){
for( int j=0; j<resultSize( vector< vector<string> >(allVecs.begin()+1, allVecs.end() ) ); j++){
result.push_back( allVecs[0][i] + enumAll(vector< vector<string> >(allVecs.begin()+1, allVecs.end() ))[j] );//enumAll on each tempVector is called multiple times. Can be optimzed.
}
}
}
Преимущество этого метода:
Это очень читабельно с точки зрения рекурсии. Он имеет легко идентифицируемый базовый шаг рекурсии, а также саму рекурсию. Он работает следующим образом: каждая итерация рекурсии перечисляет все возможные строки из n-1 векторов, а текущий шаг просто перечисляет их.
Недостатки этого метода:
1. Функция enumAll () вызывается несколько раз, возвращая один и тот же результат.
2. Тяжелое использование стека, поскольку это не хвостовая рекурсия.
Мы можем исправить (1.), выполнив следующее, но если мы не устраняем хвостовую рекурсию, мы не можем избавиться от (2.).
vector<string> enumAll(const vector< vector<string> > allVecs )
{
//__ASSERT( allVecs.size() > 0 );
vector<string> result;
if( allVecs.size() == 1 ){
for( int i=0 ; i< allVecs[0].size(); i++){
result.push_back( allVecs[0][i] );
}
return result;
}
const vector< vector<string> > tempVector(allVecs.begin()+1, allVecs.end() );
vector<string> tempResult = enumAll( tempVector );// recurse
int size = resultSize( tempVector );
cout << size << " " << tempResult.size() << endl;
for( int i=0; i<allVecs[0].size(); i++ ){
for( int j=0; j<size; j++){
result.push_back( allVecs[0][i] + tempResult[j] );
}
}
}