Shortest path to transform one word into another

后端 未结 9 2296
梦如初夏
梦如初夏 2020-12-01 00:44

For a Data Structures project, I must find the shortest path between two words (like \"cat\" and \"dog\"), changing only one letter at a time. We a

相关标签:
9条回答
  • 2020-12-01 01:02

    There are methods of varying efficiency for finding links - you can construct a complete graph for each word length, or you can construct a BK-Tree, for example, but your friend is right - BFS is the most efficient algorithm.

    There is, however, a way to significantly improve your runtime: Instead of doing a single BFS from the source node, do two breadth first searches, starting at either end of the graph, and terminating when you find a common node in their frontier sets. The amount of work you have to do is roughly half what is required if you search from only one end.

    0 讨论(0)
  • 2020-12-01 01:04
    bool isadjacent(string& a, string& b)
    {
      int count = 0;  // to store count of differences
      int n = a.length();
    
      // Iterate through all characters and return false
      // if there are more than one mismatching characters
      for (int i = 0; i < n; i++)
      {
        if (a[i] != b[i]) count++;
        if (count > 1) return false;
      }
      return count == 1 ? true : false;
    }
    

    // A queue item to store word and minimum chain length // to reach the word.

    struct QItem
    {
      string word;
      int len;
    };
    

    // Returns length of shortest chain to reach 'target' from 'start' // using minimum number of adjacent moves. D is dictionary

    int shortestChainLen(string& start, string& target, set<string> &D)
    {
      // Create a queue for BFS and insert 'start' as source vertex
      queue<QItem> Q;
      QItem item = {start, 1};  // Chain length for start word is 1
      Q.push(item);
    
      // While queue is not empty
      while (!Q.empty())
      {
        // Take the front word
        QItem curr = Q.front();
        Q.pop();
    
        // Go through all words of dictionary
        for (set<string>::iterator it = D.begin(); it != D.end(); it++)
        {
            // Process a dictionary word if it is adjacent to current
            // word (or vertex) of BFS
            string temp = *it;
            if (isadjacent(curr.word, temp))
            {
                // Add the dictionary word to Q
                item.word = temp;
                item.len = curr.len + 1;
                Q.push(item);
    
                // Remove from dictionary so that this word is not
                // processed again.  This is like marking visited
                D.erase(temp);
    
                // If we reached target
                if (temp == target)
                  return item.len;
            }
        }
      }
      return 0;
    }
    
    // Driver program
    int main()
    {
      // make dictionary
      set<string> D;
      D.insert("poon");
      D.insert("plee");
      D.insert("same");
      D.insert("poie");
      D.insert("plie");
      D.insert("poin");
      D.insert("plea");
      string start = "toon";
      string target = "plea";
      cout << "Length of shortest chain is: "
           << shortestChainLen(start, target, D); 
      return 0; 
    }
    

    Copied from: https://www.geeksforgeeks.org/word-ladder-length-of-shortest-chain-to-reach-a-target-word/

    0 讨论(0)
  • 2020-12-01 01:14

    My gut feeling is that your friend is correct, in that there isn't a more efficient solution, but that is assumming you are reloading the dictionary every time. If you were to keep a running database of common transitions, then surely there would be a more efficient method for finding a solution, but you would need to generate the transitions beforehand, and discovering which transitions would be useful (since you can't generate them all!) is probably an art of its own.

    0 讨论(0)
提交回复
热议问题