// Source : https://oj.leetcode.com/problems/word-ladder-ii/ // Author : Hao Chen // Date : 2014-10-13 /********************************************************************************** * * Given two words (start and end), and a dictionary, find all shortest transformation * sequence(s) from start to end, such that: * * Only one letter can be changed at a time * Each intermediate word must exist in the dictionary * * For example, * * Given: * start = "hit" * end = "cog" * dict = ["hot","dot","dog","lot","log"] * * Return * * [ * ["hit","hot","dot","dog","cog"], * ["hit","hot","lot","log","cog"] * ] * * Note: * * All words have the same length. * All words contain only lowercase alphabetic characters. * * **********************************************************************************/ #include #include #include #include #include using namespace std; // Solution // // 1) Using BSF algorithm build a tree like below // 2) Using DSF to parse the tree to the transformation path. // // For example: // // start = "hit" // end = "cog" // dict = ["hot","dot","dog","lot","log","dit","hig", "dig"] // // +-----+ // +-------------+ hit +--------------+ // | +--+--+ | // | | | // +--v--+ +--v--+ +--v--+ // | dit | +-----+ hot +---+ | hig | // +--+--+ | +-----+ | +--+--+ // | | | | // | +--v--+ +--v--+ +--v--+ // +----> dot | | lot | | dig | // +--+--+ +--+--+ +--+--+ // | | | // +--v--+ +--v--+ | // +----> dog | | log | | // | +--+--+ +--+--+ | // | | | | // | | +--v--+ | | // | +--->| cog |<-- + | // | +-----+ | // | | // | | // +----------------------------------+ map< string, unordered_set >& buildTree(string& start, string& end, unordered_set &dict) { static map< string, unordered_set > parents; parents.clear(); unordered_set level[3]; unordered_set *previousLevel = &level[0]; unordered_set *currentLevel = &level[1]; unordered_set *newLevel = &level[2]; unordered_set *p =NULL; currentLevel->insert(start); bool reachEnd = false; while( !reachEnd ) { newLevel->clear(); for(auto it=currentLevel->begin(); it!=currentLevel->end(); it++) { for (int i=0; isize(); i++) { string newWord = *it; for(char c='a'; c<='z'; c++){ newWord[i] = c; if (newWord == end){ reachEnd = true; parents[*it].insert(end); continue; } if ( dict.count(newWord)==0 || currentLevel->count(newWord)>0 || previousLevel->count(newWord)>0 ) { continue; } newLevel->insert(newWord); //parents[newWord].insert(*it); parents[*it].insert(newWord); } } } if (newLevel->empty()) break; p = previousLevel; previousLevel = currentLevel; currentLevel = newLevel; newLevel = p; } if ( !reachEnd ) { parents.clear(); } return parents; } void generatePath( string start, string end, map< string, unordered_set > &parents, vector path, vector< vector > &paths) { if (parents.find(start) == parents.end()){ if (start == end){ paths.push_back(path); } return; } for(auto it=parents[start].begin(); it!=parents[start].end(); it++){ path.push_back(*it); generatePath(*it, end, parents, path, paths); path.pop_back(); } } vector< vector > findLadders(string start, string end, unordered_set &dict) { vector< vector > ladders; vector ladder; ladder.push_back(start); if (start == end){ ladder.push_back(end); ladders.push_back(ladder); return ladders; } map< string, unordered_set >& parents = buildTree(start, end, dict); if (parents.size()<=0) { return ladders; } generatePath(start, end, parents, ladder, ladders); return ladders; } void printLadders(vector< vector > &ladders){ int i, j; for (i=0; i "; } cout << ladders[i][j] << endl; } } int main(int argc, char** argv) { string start = "hit"; string end = "cog"; //unordered_set dict ({"hot","dot","dog","lot","log"}); unordered_set dict ({"bot","cig", "cog", "dit", "dut", "hot", "hit" ,"dot","dog","lot","log"}); vector< vector > ladders; ladders = findLadders(start, end, dict); printLadders(ladders); return 0; }