package com.interview.algorithms.string;
import java.util.*;
/**
* Created with IntelliJ IDEA.
* User: stefanie
* Date: 8/29/14
* Time: 4:25 PM
*
* Given several sets of strings, write code to combine the sets which interactions.
* Such as {aa,bb,cc},{bb,dd},{hh},{uu,jj},{dd,kk}, the result should be {aa,bb,cc,dd,kk},{hh},{uu,jj}
*
* 1. using reverseIndex to build a reference graph using mark[]
* 2. run UnionFind to combine mark[]
* 3. combine the set and delete duplicate ones
*/
public class C11_25_StringSetCombine {
public static List<Set<String>> combine(List<Set<String>> input) {
int[] mark = new int[input.size()];
for(int i = 0; i < mark.length; i++) mark[i] = i;
//build index
Map<String, List<Integer>> reverseIndex = new HashMap<String, List<Integer>>();
for(int i = 0; i < input.size(); i++){
for (String str : input.get(i)) {
List<Integer> index = reverseIndex.get(str);
if (index == null) {
index = new ArrayList<>();
reverseIndex.put(str, index);
}
if(!index.contains(mark[i]))
index.add(mark[i]);
}
}
boolean hasChange = true;
//change flag
for(List<Integer> indexs : reverseIndex.values()){
if(indexs.size() > 1){
hasChange = true;
for(int i = 1; i < indexs.size(); i++){
mark[indexs.get(i)] = indexs.get(0);
}
}
}
while(hasChange){
hasChange = false;
for(int i = 0; i < mark.length; i++){
if(mark[mark[i]] != mark[i]) {
mark[i] = mark[mark[i]];
hasChange = true;
}
}
}
//combine the set
boolean[] save = new boolean[mark.length];
for(int i = 0; i < mark.length; i++) save[mark[i]] = true;
for(int i = 0; i < mark.length; i++) input.get(mark[i]).addAll(input.get(i));
for(int i = save.length - 1; i >= 0; i--) {
if(!save[i]) input.remove(i);
}
return input;
}
}