题意:给定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;
}
02-12 06:08