如何在带有给定特定前缀的向量中打印出单词

How to Print Out the Words In a Trie With a Vector Given a Particular Prefix

本文关键字:向量 打印 单词 前缀      更新时间:2023-10-16

我目前正在做一个项目,在这个项目中,我需要打印出与给定前缀匹配的 trie 中的单词,由用户使用字符串向量打印出单词。但是,我很难开始这样做,并希望你们能给我任何建议。

这是我的意思的一个例子

trie 中的单词 { app, address, add, beg, cow, mice}前缀给定广告使用矢量打印出包含前缀 AD 的字词:地址加

非常感谢您提供的任何帮助。

首先,trie 是一棵树。

在trie中,所有具有给定前缀(例如ad(的单词实际上都存储在trie的子树中,该子树在搜索前缀ad时被访问。
因此,要打印trie中具有给定前缀的所有单词,请分2个步骤完成:

  1. 查找与您的前缀对应的节点node
  2. 列出子树中以 node 为根的所有单词。

这是一个伪代码:

find_all_words_starting_with(string prefix, trieNode node, int depth){
    if (depth == length(prefix)){
        suffix = empty_string
        print_all_words_with_prefix(prefix, suffix, node)
    } else {
        letter = prefix[depth]
        if (node.hasChild(letter)){
            find_all_words_starting_with(prefix, node.getChild(letter), depth+1)
        } else { // no word with the correct prefix
            return
        }
    }
}
print_all_words_with_prefix(prefix, suffix, node){
    if (node.isCompleteWord){
        print(prefix + suffix)
    }
    for each letter c in the alphabet {
        if (node.hasChild(c)){
            print_all_words_with_prefix(prefix, suffix + c, node.getChild(c))
        }
    }
}

find_all_words_starting_with完成工作的第一部分。它找到与前缀对应的节点,并调用第二个函数 print_all_words_with_prefix ,它将打印子树中的所有完整单词。

这在很大程度上取决于trie的实现,尽管我在下面提供了一个示例trie。

每个尝试包含三件事:

  • 一堆树枝
  • 根(可能为空(
  • 一个布尔值,说明这个trie是否代表一个完整的单词

基于此,我们可以做一些事情,例如在trie中添加单词,检查单词是否在trie中,并对trie中的所有单词应用函数。我提供成员函数来执行这些操作。

#include <memory>
#include <iterator>
struct WordTrie {
    static int index_from_char(char c) {
        return (unsigned char)c; 
    }
    static int char_from_index(int index) {
        return (char)(unsigned char)index; 
    }
    std::unique_ptr<WordTrie[]> branches; 
    WordTrie* root; 
    bool is_complete_word = false; 
    // Make an empty Trie
    WordTrie() : branches(nullptr), root(nullptr) {}
    // Make a WordTrie with the given root
    WordTrie(WordTrie* root) : branches(nullptr), root(root) {}

    int get_index_in_root() const {
        WordTrie const* branch_zero = root->branches.get();
        return std::distance(branch_zero, this); 
    }
    void append_char(std::string& s) {
        if(root != nullptr) {
            s += char_from_index(get_index_in_root()); 
        }
    }
    void add_word(char const* str, int length) {
        if(length > 0) {
            char c = *str; 
            if(branches == nullptr) {
                branches.reset(new WordTrie[256]); 
                for(int i = 0; i < 256; i++) {
                    branches[i].root = this; 
                }
            }
            branches[index_from_char(c)].add_word(str + 1, length - 1); 
        } else {
            is_complete_word = true; 
        }
    }
    bool has_word(char const* str, int length) {
        if(length == 0) {
            return is_complete_word; 
        }
        return branches[index_from_char(*str)].has_word(str + 1, length - 1); 
    }
    bool has_word(std::string const& s) {
        return has_word(s.data(), s.size()); 
    }
    template<class F>
    void apply_over_words_in_trie(std::string const& word, F&& func) {
        if(is_complete_word) {
            func(word); 
        }
        // Exit if there are no branches
        if(branches == nullptr) return; 
        //Add character to 'word'
        std::string new_word = word + '_';
        for(int i = 0; i < 256; i++) {
            new_word.back() = char_from_index(i); 
            branches[i].apply_over_words_in_trie(new_word, func); 
        }
    }
};