简体   繁体   中英

Finding the longest word from a digital tree (trie) in C++

For an assignment, I had to make two methods, one prints out a digital tree storing a few words and marks a * next to an actual word. The other method is supposed to find the longest word in this digital tree. Here is the defined class (with my completed print method):

class DTN {
  public:
    DTN () :
      is_word(false), word_to_here(""), children()
    {}
    DTN (bool iw, std::string wth) :
      is_word(iw), word_to_here(wth), children()
    {}

    bool                     is_word;
    std::string              word_to_here;
    ics::ArrayMap<char,DTN>  children;
};


//Add a word correctly into a Digital Tree (of strings)
void add_a_word (DTN& dtn, std::string prefix, std::string postfix) {
  if (postfix.size() == 0) {
    dtn.is_word = true;
    return;
  } else {
    char first = postfix[0];
    if (!dtn.children.has_key(first))
      dtn.children[first] = DTN(false,prefix+first);
    return add_a_word(dtn.children[first],prefix+first,postfix.substr(1));
  }
}


//Print dtn, its n children indenter, their n children indented....
void print_DTN_tree(const DTN& dtn, std::string indent) {
  std::cout << indent << dtn.word_to_here  << (dtn.is_word? "*" : "") << std:: endl;
  for (auto n : dtn.children)
    print_DTN_tree(n.second, indent+"  ");
}


bool is_a_word (const DTN& dtn, std::string remaining_letters) {
  if (remaining_letters.empty())
    return dtn.is_word;          //all letters in tree; is it a word?
  else if (dtn.children.has_key(remaining_letters[0]) == false)
    return false;                 //some letters not in truee: it isn't a word
  else
    return is_a_word(dtn.children[remaining_letters[0]], //check the next letter
                     remaining_letters.substr(1));
  }


void add_a_word (DTN& dtn, std::string word) {
  add_a_word(dtn,"",word);
} 

std::string longest_word (const DTN& dtn) {
// add this method
}

I got the printing method to work with a mix of iteration and recursion, and thought that finding the longest word would be similar, meaning all I would need to do would be to iterate over my tree, call a function that checks if it's a word, and if it is, compare it to the current longest word, but when it finds the longest word, it doesn't automatically return, and keeps going to the next word. How should I go about solving this, (or even a general idea on how to solve this would be appreciated, given the class), with my current implementation?

There are several ways to implement this, here's the simplest (but the least efficient one):

DTN *best_match=nullptr;

find_longest(root_dtn_node, &best_match);

if (best_match != nullptr)
{
    // ... That's the longest word here
}

// ================================================================

void find_longest(DTN &node, DTN **best_match)
{
      if (
          // Check if the node is a word. If so, then if *best_match
          // is null, or if that word is shorter than the word represent
      )
      {
            *best_match= &node;
      }

      // Now, recurse to all child nodes
}

I think you can figure out how to fill in the spots marked with comments. When the recursion unwinds and find_longest returns, a non-NULL best_match will point to the node with the longest word.

It's up to you to define what happens when there are two or more words with the same, longest length.

One other comment. Consider taking the code that iterates over the tree and putting it into a template function, parametrized by a lambda class, with the template class iterating over the entire tree, and invoking the lambda for each node representing a word. This way you will avoid duplicating the code that executes the recursion between your existing function that prints the tree, and this one.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM