题意:给定n张卡片,每张卡片都有k个特性,每个特性有三个选项'T','S','E',找出这n张卡片中其中三张卡片,如果这三张卡片的k个特性的每一个特性都相同或者都不相同,统计合理的数量。
分析:我们可以从n张卡片中枚举两张卡片,然后构造出由这两张卡片得到的第三张卡片,因为只有三个特性选项,如果这两张卡片的特性相同,那么第三张卡片的特性也相同,如果不同,那么可以推出第三张卡片的特性,然后判断构造好的卡片是否存在。判断存不存在,我们可以用unordered_set,读入字符串的同时,插入set,然后使用set的count或者find函数查找
因为我们枚举i,j来构造第三张卡片,如果存在,意味着后面的组合会重复3次,因此答案需要除以3次。
分析时间复杂度:枚举了两张卡片,时间复杂度为\(o(n^2)\),然后平衡树的查找为\(o(log(n))\),总的时间复杂度为\(o(n^2*log(n))\)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <unordered_set>
#include <algorithm>
using namespace std;
const int N = 1505;
unordered_set<string> sets;
string c[N];
int main()
{
//卡片的数量和特征数量
int n, k;
scanf("%d%d", &n, &k);
//枚举两张卡片,来组合第三张卡片,然后查找是否存在
//读入字符串
for (int i = 0; i < n; ++i)
{
cin >> c[i];
sets.insert(c[i]);
}
int res = 0;
string q;
q.resize(k);
int all = 'S' + 'T' + 'E';
for (int i = 1; i < n; ++i)
{
for (int j = 0; j < i; ++j)
{
//比较特征
for (int m = 0; m < k; ++m)
{
if (c[i][m] == c[j][m])
q[m] = c[i][m];
else
{
q[m] = all - c[i][m] - c[j][m];
}
//判断存不存在
}
if (sets.find(q) != sets.end())
++res;
}
}
printf("%d\n", res / 3);
return 0;
}