from typing import List
'''
并查集求连通分量个数
'''
class MergeSet:
def __init__(self):
self.m = {}
self.__root_cnt = 0
def getRoot(self, node):
root = node
buf = []
while self.m[root] != root:
buf.append(root)
root = self.m[root]
for node in buf:
self.m[node] = root
return root
def merge(self, a, b):
for node in [a, b]:
if node not in self.m:
self.m[node] = node
self.__root_cnt += 1
root1 = self.getRoot(a)
root2 = self.getRoot(b)
if root1 != root2:
self.m[root1] = root2
self.__root_cnt -= 1
def isInSameSet(self, a, b):
for node in [a, b]:
if node not in self.m:
return False
return self.getRoot(a) == self.getRoot(b)
def getRootNum(self):
return self.__root_cnt
def getClusters(self):
rec = {}
for node in self.m:
root = self.getRoot(node)
if root not in rec:
rec[root] = []
rec[root].append(node)
return [nodes for nodes in rec.values()]
class Solution:
def numSimilarGroups(self, A: List[str]) -> int:
def check(str1, str2):
if str1 == str2:
return True
cnt = 0
for i in range(len(str1)):
if str1[i] != str2[i]:
cnt += 1
if cnt >= 3:
return False
return cnt == 2
N, M = len(A), len(A[0])
if N <= M:
merge_set = MergeSet()
for i in range(len(A)):
merge_set.merge(i, i)
for i in range(len(A)):
for j in range(i+1, len(A)):
str1, str2 = A[i], A[j]
if (not merge_set.isInSameSet(i, j)) and check(str1, str2):
merge_set.merge(i, j)
return merge_set.getRootNum()
else:
merge_set = MergeSet()
for word in A:
merge_set.merge(word, word)
all_words = set(A)
for word in A:
for i in range(len(word)):
for j in range(i+1, len(word)):
new_word = word[:i] + word[j] + word[i+1:j] + word[i] + word[j+1:]
if new_word in all_words:
merge_set.merge(word, new_word)
return merge_set.getRootNum()