检查向量是否具有所有可能的字符组合

Check if vector has all possible combinations of characters

本文关键字:有可能 字符 组合 向量 是否 检查      更新时间:2023-10-16

我发现了许多其他问题,这些问题询问如何将"A"B"C"的所有可能组合创建到向量中,但是 我正在尝试找到一种更简单的方法,如何检查我的向量是否包含许多不同且相同的"A"B"C"组合(重复例如。AAA 和 CAA) 包含这三个字符的所有可能组合。

我打算使每个不同的字符组合等于不同的数字,并有一个如下所示的 switch 语句,该语句在匹配时将每个大小写更改为 true,最后有一个 if 语句检查是否所有情况都为 true。

但我觉得好像有一种更简单的方法可以做到这一点......

我仍然是c ++的新手,因此非常感谢任何帮助或建议

vector<string> myVector = {"ABC", "CBA"};
bool case1 = false;
for(int i = 0; i < myVector.size(); i++){
switch(myVector[i]){
case 11:
case1 = true;
break;
...
}        
}
  • 将字符串的所有排列存储在vector
  • 将其与输入向量进行比较

一个最小的示例如下所示:

#include <algorithm>
#include <string>
#include <iostream>
int main()
{
std::string s = "ABC";
std::vector<string> perString;
std::vector<string> inputVector = {"ABC", "ACB", "BAC", "BCA", "CAB", "CBA"}; 
do {
perString.push_back(s);
} while(std::next_permutation(s.begin(), s.end()));
if(perString == inputVector)
std::cout<< "YES, the vector has all possible combinations of characters" << 'n';
else
std::cout<< "NO, It doesn't" << 'n';       
return 0;
}
  • 过滤向量以仅包含有效的字符串(因此,如果您只想从'A''B''C'的字母中拒绝"AZA")
  • std::sort/std::unique其内容。(所以"AAA", "ABA", "AAA"}->{"AAA", "ABA"})。
  • 然后检查矢量大小与预期大小(3 ** 327在您的情况下($alphabetSize ** $stringSize))。

解决此问题的一种方法是对要检查的组合向量进行排序(如果尚未检查),然后将元素与所有可能的(排序的)组合进行比较。由于排序阶段,这种方法的时间复杂度为 O(C * log C),其中 C 是输入向量的元素数。

C 可以很大,给定 n 作为可能元素的数量和 k 作为所选元素的数量,所有可能与重复的组合都是nk(在 OP 的例子中,它是 3 ^ 3 = 27)。

另一种方法,不需要对初始向量进行排序,也不需要实际生成排序的组合,类似于在哈希表中搜索值。

如果可以对所有组合进行排序,则也可以对它们进行索引。因此,您可以计算由要测试的字符串表示的特定组合的"索引",并计算找到的有效组合的数量。

这是一个可能的实现:

#include <iostream>
#include <string>
#include <vector>
// Transforms a string representing a combination into the index of that
// combination in the set of all possible combinations
size_t index_of(std::string const &candidate, std::string const &source);
// Check if the the vector 'combs' contains all the possible combinations
// of 'k' elements of string 'base'
bool are_there_all_the_possible_combinations(std::string const &base,
size_t k,
std::vector<std::string> const &combs);
int main()
{
std::string base {"ABC"};
std::vector<std::string> combs {
"AAA", "AAB", "AAC", "ABA", "ABB", "ABC", "ACA", "ACB", "ACC",
"BAA", "BAB", "BAC", "BBA", "BBB", "BBC", "BCA", "BCB", "BCC",
"CAA", "CAB", "CAC", "CBA", "CBB", "CBC", "CCA", "CCB", "CCC"
};
size_t k = 3;
std::cout << ( are_there_all_the_possible_combinations(base, k, combs)
? "Yesn" : "Non" );              // <-- it should output 'Yes'
combs.erase( std::remove( combs.begin(), combs.end(), "BCA" ), combs.end() );
std::cout << ( are_there_all_the_possible_combinations(base, k, combs)
? "Yesn" : "Non" );              // <-- it should output 'No'
combs.push_back("BCA");              // <-- Note that now the vector isn't sorted.
std::cout << ( are_there_all_the_possible_combinations(base, k, combs)
? "Yesn" : "Non" );              // <-- it should output 'Yes'
}
// Calculate base ^ exponent (using size_t, not floating point math)
constexpr size_t ull_pow(size_t base, size_t exponent)
{
size_t result = 1;
for (;;)
{
if (exponent & 1)
result *= base;
exponent >>= 1;
if (exponent == 0)
break;
base *= base;
}
return result;
}

// Counts the number of valid combinations and check if it equals the total
bool are_there_all_the_possible_combinations(std::string const &base,
size_t k,
std::vector<std::string> const &combs)
{
size_t total_combinations = ull_pow(base.size(), k);
std::vector<bool> combinations(total_combinations);
size_t count = 0;
for (auto const & str : combs)
{
if (str.size() != k)
{
// You can either ignore those mismatches or break
continue;
}
size_t pos = index_of(str, base);
if (pos == std::string::npos)
{   
// This string doesn't belong to the possible combinations. It's
// unclear if OP want to ignore this case or consider it a mismatch
continue;
}
if ( combinations[pos] )
{
// This is a duplicate. Again, it can be ignored or not.
continue;
}
combinations[pos] = true;
++count;
}
return count == total_combinations;    
}
// Evaluate the index as a number in base n (number of elements in the base string)
size_t index_of(std::string const &candidate, std::string const &source)
{
size_t result = 0, base = 1;
for (auto c = candidate.crbegin(); c != candidate.crend(); ++c)
{
size_t pos = source.find(*c);
if (pos == std::string::npos)
return std::string::npos;
result += pos * base;
base *= source.size();
}
return result;
}