class Solution {
public:
struct Edge{
int from;
int to;
int pre;
Edge(int a,int b,int c):from(a),to(b),pre(c){}
};
vector<Edge> E;
int cnt;
vector<int> pre;
vector<int> vis;
void addEdge(int from,int to){
E.push_back(Edge(from,to,pre[from]));
pre[from] = cnt++;
E.push_back(Edge(to,from,pre[to]));
pre[to] = cnt++;
}
void dfs(int S){
vis[S] = 1;
for(int i=pre[S];i!=0;i=E[i].pre){
if(vis[E[i].to] == 0) dfs(E[i].to);
}
}
bool judge(string& x,string& y){
int cnt = 0;
int N = x.length();
for(int i=0;i<N;i++){
if(x[i] != y[i]) cnt++;
if(cnt > 2) return false;
}
return true;
}
int numSimilarGroups(vector<string>& A) {
int N = A.size();
int ans = 0;
cnt = 1;
E.push_back(Edge(0,0,0));
pre.reserve(N);
vis.reserve(N);
for(int i=0;i<N;i++) pre[i] = vis[i] = 0;
for(int i=0;i<N;i++){
for(int j=i+1;j<N;j++){
if(judge(A[i],A[j])) addEdge(i,j);
}
}
for(int i=0;i<N;i++){
if(vis[i] == 0){
dfs(i);
ans++;
}
}
return ans;
}
};