单词分类

GitHub跳转原题关系图返回列表

把每个单词内部字母排序成标准形,用集合统计不同标准形的个数,就是不同类别数。

OJ: luogu

题目 ID: P1808

难度:普及-

标签:字符串排序

日期: 2026-06-19 10:19

题意

给出 n 个只含大写字母的单词。

如果两个单词中每个字母出现次数完全相同,就把它们归为同一类。

要求输出总共有多少类。

思路

这题的关键是给每个单词找一个统一的“标准形”。

最直接的教学版写法如下:

cpp
// brute.cpp:把每个单词排序成标准形后去重,作为教学版和对拍基准程序。
#include <bits/stdc++.h>
using namespace std;

int n;
set<string> classes_of_words;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    cin >> n;
    for (int i = 1; i <= n; i++) {
        string s;
        cin >> s;

        // 排序后的结果只和每个字母出现次数有关。
        sort(s.begin(), s.end());
        classes_of_words.insert(s);
    }

    cout << classes_of_words.size() << '\n';
    return 0;
}

把单词内部字母排序后:

  • 同类单词一定变成同一个字符串;
  • 不同类单词一定变成不同字符串。

所以我们只要:

  1. 对每个单词排序;
  2. 把排序结果放入集合;
  3. 输出集合大小。

代码

cpp
#include <bits/stdc++.h>
using namespace std;

int n;
set<string> classes_of_words;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    cin >> n;
    for (int i = 1; i <= n; i++) {
        string s;
        cin >> s;

        // 同一类单词排序后一定得到同一个标准形。
        sort(s.begin(), s.end());
        classes_of_words.insert(s);
    }

    cout << classes_of_words.size() << '\n';
    return 0;
}

复杂度

  • 时间复杂度:O(nLlogL)O(n * L log L)
  • 空间复杂度:O(nL)O(nL)

其中 L 是单词长度。

总结

这题本质上是在数“有多少种不同的标准形”。

把异位词问题转成排序后去重,是最直接也最稳的写法。