字符串归类 并查集
4304. 字符串归类
给定 n 个由小写字母构成的字符串。
现在,请你对它们进行归类。
对于两个字符串 a 和 b:
- 如果至少存在一个字母在 a 和 b 中同时出现,则 a 和 b 属于同一类字符串。
- 如果字符串 c 既与字符串 a 同类,又与字符串 b 同类,则 a 和 b 属于同一类字符串。
请问,最终所有字符串被划分为多少类。
输入格式
第一行包含整数 n。
接下来 n 行,每行包含一个仅由小写字母构成的字符串。
注意,输入字符串可能相同。
输出格式
一个整数,表示最终所有字符串被划分为的类的数量。
数据范围
前 6 个测试点满足 1≤n≤10。
所有测试点满足 1≤n≤2×105,输入字符串的长度范围 [1,50],所有输入字符串的总长度范围 [1,106],所有字符串均由小写英文字母构成。
输入样例1:
4
a
b
ab
d
输出样例1:
2
输入样例2:
3
ab
bc
abc
输出样例2:
1
输入样例3:
1
abcdefghijklmn
输出样例3:
1
思路:
st
数组标记字符是否出现过,利用并查集进行归类
代码:
#include<iostream>
using namespace std;
const int N = 27;
int n, res, p[N];
bool st[N];
int find(int x) {
if (x != p[x]) p[x] = find(p[x]);
return p[x];
}
int main() {
cin >> n;
string s;
for (int i = 0; i < N; ++i) p[i] = i;
for (int i = 0; i < n; ++i) {
cin >> s;
int t = find(s[0] - 'a');
st[s[0] - 'a'] = true;
for (int j = 1; j < s.length(); ++j) {
p[find(s[j] - 'a')] = t;
st[s[j] - 'a'] = true;
}
}
for (int i = 0; i < N; ++i)
// 出现过的每一类都只有一个成员满足p[i] == i
if (st[i] && p[i] == i)
res++;
cout << res << endl;
return 0;
}