Geeksforgeeks website has a very detailed description about the algorithm which uses topological sorting. The link is here: http://www.geeksforgeeks.org/given-sorted-dictionary-find-precedence-characters/.
As that implementation of the topological sorting which uses DFS has strong assumption, that is, vertexes should be the first V characters, for simplicity, here is my implementation that removes this assumption and throw runtime exception when there are conflict precedences (cycle) in the graph. The vertexes thus can be any characters (char). Also, here is another implementation of topological sorting which recursively find vertexes that has no incoming vertexes.
#include <iostream> #include <string> #include <vector> #include <stack> #include <unordered_set> #include <unordered_map> using namespace std; void insert(unordered_map<char, unordered_set<char> > &outgoing, unordered_map<char, unordered_set<char> > &incoming, char from, char to) { if (outgoing.find(from) == outgoing.end()) { outgoing[from] = unordered_set<char>(); } outgoing[from].insert(to); if (incoming.find(to) == incoming.end()) { incoming[to] = unordered_set<char>(); } incoming[to].insert(from); } void DFS(unordered_map<char, unordered_set<char> > &Adj, unordered_map<char, bool> &visited, stack<char> &orders, unordered_map<char, bool> &tmp, char vertex) { visited[vertex] = true; for (unordered_set<char>::iterator iter = Adj[vertex].begin(); iter != Adj[vertex].end(); ++iter) { if (tmp.find(*iter) != tmp.end() && tmp[*iter]) { throw runtime_error("there is a cycle in the graph"); } tmp[*iter] = true; if (!visited[*iter]) { DFS(Adj, visited, orders, tmp, *iter); } } orders.push(vertex); } vector<char> orderofcharacters_DFS(std::vector<string> words) { unordered_set<char> vertexes; unordered_map<char, unordered_set<char> > Adj; for (int i = 0; i < words.size() - 1; ++i) { int j = 0, minsize = min(words[i].size(), words[i + 1].size()); while (j < minsize && words[i][j] == words[i + 1][j]) { j++; } if (j != minsize) { if (Adj.find(words[i][j]) == Adj.end()) { Adj[words[i][j]] = unordered_set<char>(); } Adj[words[i][j]].insert(words[i + 1][j]); vertexes.insert(words[i][j]); vertexes.insert(words[i + 1][j]); } } unordered_map<char, bool> visited; for (unordered_set<char>::iterator iter = vertexes.begin(); iter != vertexes.end(); ++iter) { visited[*iter] = false; } stack<char> orders; for (unordered_set<char>::iterator iter = vertexes.begin(); iter != vertexes.end(); ++iter) { if (!visited[*iter]) { unordered_map<char, bool> tmp; tmp[*iter] = true; DFS(Adj, visited, orders, tmp, *iter); } } std::vector<char> res; while (!orders.empty()) { res.push_back(orders.top()); orders.pop(); } return res; } vector<char> orderofcharacters_TOPO(std::vector<string> words) { unordered_set<char> vertexes; unordered_map<char, unordered_set<char> > incoming; unordered_map<char, unordered_set<char> > outgoing; for (int i = 0; i < words.size(); ++i) { for (int k = 0; k < words[i].size(); ++k) { vertexes.insert(words[i][k]); } for (int j = i + 1; j < words.size(); ++j) { if (words[i][0] != words[j][0]) { // orders.insert(make_pair<char, char>(words[i][0], words[j][0])); insert(outgoing, incoming, words[i][0], words[j][0]); } else { int k = 1; while (k < words[i].size() & k < words[j].size() & words[i][k] == words[j][k]) { k++; } if (k == words[i].size() || k == words[j].size()) { continue; } insert(outgoing, incoming, words[i][k], words[j][k]); } } } std::vector<char> res; unordered_set<char> noincoming; for (unordered_set<char>::iterator iter = vertexes.begin(); iter != vertexes.end(); ++iter) { if (incoming.find(*iter) == incoming.end()) { noincoming.insert(*iter); } } while (!noincoming.empty()) { char c = *noincoming.begin(); res.push_back(c); noincoming.erase(noincoming.begin()); vertexes.erase(c); if (outgoing.find(c) != outgoing.end()) { for (unordered_set<char>::iterator iter = outgoing[c].begin(); iter != outgoing[c].end(); ++iter) { incoming[*iter].erase(c); if (incoming[*iter].size() == 0) { noincoming.insert(*iter); } } } } if (vertexes.size() != 0) { throw runtime_error("cannot compare"); } return res; } int main() { vector<string> words; // b, d, a, c words.push_back("baa"); words.push_back("abcd"); words.push_back("abca"); words.push_back("cab"); words.push_back("cad"); // c, a, b // words.push_back("caa"); // words.push_back("aaa"); // words.push_back("aab"); // cycle // words.push_back("aba"); // words.push_back("bba"); // words.push_back("aaa"); std::vector<char> orders = orderofcharacters_DFS(words); for (int i = 0; i < orders.size(); ++i) { cout<<orders[i]<<endl; } return 0; }