题意:给定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;
}