Lexicographically Smallest Equivalent String
MediumStringUnion Find
Solution
import { range } from '@algorithm/lib';
export function smallestEquivalentString(s1: string, s2: string, baseStr: string): string {
const n = s1.length;
const graph = new Map<string, Set<string>>();
const addGraphItem = (key: string, value: string) => {
const graphItem = graph.get(key);
if (graphItem === undefined) {
graph.set(key, new Set(value));
} else {
graphItem.add(value);
}
};
for (const i of range(n)) {
const [c1, c2] = [s1[i], s2[i]];
addGraphItem(c1, c2);
addGraphItem(c2, c1);
}
const lexicographicallySmallest = findLexicographicallySmallest(graph);
return [...baseStr].reduce(
(prev, curr) => prev + (lexicographicallySmallest.get(curr) || curr),
'',
);
}
const findLexicographicallySmallest = (graph: Map<string, Set<string>>): Map<string, string> => {
const lexicographicallySmallest = new Map<string, string>();
const findLexicographicallySmallestPerGroup = (startChar: string) => {
const group = new Set<string>(startChar);
let queue = [startChar];
let smallestChar = startChar;
while (0 < queue.length) {
const nextQueue = [];
for (const currentChar of queue) {
const nextChars = graph.get(currentChar);
if (nextChars === undefined) {
continue;
}
for (const nextChar of nextChars) {
if (!group.has(nextChar)) {
group.add(nextChar);
nextQueue.push(nextChar);
if (nextChar < smallestChar) {
smallestChar = nextChar;
}
}
}
}
queue = nextQueue;
}
for (const char of group.values()) {
lexicographicallySmallest.set(char, smallestChar);
}
};
for (const char of graph.keys()) {
if (!lexicographicallySmallest.has(char)) {
findLexicographicallySmallestPerGroup(char);
}
}
return lexicographicallySmallest;
};