There is a new alien language which uses the latin alphabet. However, the order among letters are unknown to you. You receive a list of non-empty words from the dictionary, where words are sorted lexicographically by the rules of this new language. Derive the order of letters in this language.
class Solution {
public:
/**
* @param words: a list of words
* @return: a string which is correct order
*/
string alienOrder(vector<string> &words) {
unordered_map<char, unordered_set<char>> edges;
unordered_map<char, int> inorder;
for (int i = 1; i < words.size(); ++i) {
const auto &pre = words[i - 1], &cur = words[i];
int j = 0, mi = min(pre.length(), cur.length());
for (; j < mi; ++j) {
if (pre[j] != cur[j]) {
edges[pre[j]].insert(cur[j]);
if (!inorder.count(cur[j])) inorder[cur[j]] = 0;
if (!inorder.count(pre[j])) inorder[pre[j]] = 0;
++inorder[cur[j]];
break;
}
}
if (j == mi && cur.length() < pre.length()) return "";
}
set<char> chars;
for (const auto w : words) {
for (const auto n : w) {
chars.insert(n);
}
}
queue<char> q;
for (const auto &p : inorder) {
if (p.second == 0) q.push(p.first);
}
string res;
while (!q.empty()) {
const auto &t = q.front();
res.push_back(t);
chars.erase(t);
for (const auto c : edges[t]) {
--inorder[c];
if (inorder[c] == 0) q.push(c);
}
q.pop();
}
// If the order is invalid, return an empty string.
if (res.length() != inorder.size()) return "";
// There may be multiple valid order of letters, return the smallest in normal lexicographical order
int i = 0;
string r;
while (!chars.empty() && i < res.size()) {
const auto a = *chars.begin(), b = res[i];
if (a < b) {
r += a;
chars.erase(a);
} else {
r += b;
++i;
}
}
for (const auto c : chars) r += c;
for (; i < res.size(); ++i) r += res[i];
return r;
}
};