​linkkkk​

题意:

给出Codeforces 1263D.Secret Passwords(并查集 思维)_字符串个字符串,如果两个字符串中含有相同的字母说明两个字符串相同,问有多少个不同的字符串。

思路:

具有传递性,如果Codeforces 1263D.Secret Passwords(并查集 思维)_字符串_02相同,Codeforces 1263D.Secret Passwords(并查集 思维)_i++_03相同,那么Codeforces 1263D.Secret Passwords(并查集 思维)_#include_04也一定相同
考虑用并查集维护。
但是Codeforces 1263D.Secret Passwords(并查集 思维)_算法_05所以枚举两个字符串显然不现实。
一共只有Codeforces 1263D.Secret Passwords(并查集 思维)_算法_06个字母,维护在某个字符串里每个字母的出现次数,如果Codeforces 1263D.Secret Passwords(并查集 思维)_算法_07两个字母在这个字符串里都出现过,合并Codeforces 1263D.Secret Passwords(并查集 思维)_算法_07所在集合,这样就能实现传递性了。

代码:

// Problem: D. Secret Passwords
// Contest: Codeforces - Codeforces Round #603 (Div. 2)
// URL: https://codeforces.com/problemset/problem/1263/D
// Memory Limit: 256 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)

#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<sstream>
using namespace std;

typedef long long ll;

const int maxn=2e5+100;

int root[30],vis[30],siz[30];

int Find(int x){
if(x!=root[x]) root[x]=Find(root[x]);
return root[x];
}

int main() {
for(int i=0;i<=27;i++) root[i]=i;
int n;cin>>n;
for(int i=1;i<=n;i++){
string s;cin>>s;
memset(siz,0,sizeof siz);
for(int j=0;s[j];j++){
int now=s[j]-'a'+1;
siz[now]++;vis[now]=1;
}
for(int j=1;j<=26;j++){
if(!siz[j]) continue;
for(int k=1;k<=26;k++){
if(!siz[k]) continue;
int fu=Find(j),fv=Find(k);
if(fu!=fv) root[fu]=fv;
}
}
}
int ans=0;
for(int i=1;i<=26;i++){
// if(i<=4) cout<<i<<" "<<Find(i)<<" "<<ans<<endl;
if(vis[i]&&i==Find(i)) ans++;
}

cout<<ans<<endl;

return 0;
}