212. 单词搜索 II(字典树/前缀树)

给定一个 m x n 二维字符网格 board 和一个单词(字符串)列表 words, 返回所有二维网格上的单词 。

单词必须按照字母顺序,通过 相邻的单元格 内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。

 

示例 1:

输入:board = [["o","a","a","n"],["e","t","a","e"],["i","h","k","r"],["i","f","l","v"]], words = ["oath","pea","eat","rain"]
输出:["eat","oath"]

示例 2:

输入:board = [["a","b"],["c","d"]], words = ["abcb"]
输出:[]

 

提示:

  • m == board.length
  • n == board[i].length
  • 1 <= m, n <= 12
  • board[i][j] 是一个小写英文字母
  • 1 <= words.length <= 3 * 104
  • 1 <= words[i].length <= 10
  • words[i] 由小写英文字母组成
  • words 中的所有字符串互不相同

 

字典树/前缀树,模板题。最初版本见题号208,实现字典树。进阶如题号472,字典树+dfs记忆化搜索这类。

class Solution {
public:
struct Trie
{
    Trie* child[26];
    string word = "";
    Trie() {
        for (int i = 0; i < 26; i++)
            child[i] = nullptr;
    }
};
    vector<string> ans;
    
    void dfs(vector<vector<char>>& board,Trie* t,int i,int j)
    {
        char c=board[i][j];
        if(c=='*'||t->child[c-'a']==nullptr) return;
        t=t->child[c-'a'];
        if(t->word!="")
        {
            ans.push_back(t->word);
            t->word="";
        }
        board[i][j]='*';
        if(i+1<board.size())dfs(board,t,i+1,j);
        if(i-1>=0)dfs(board,t,i-1,j);
        if(j+1<board[i].size())dfs(board,t,i,j+1);
        if(j-1>=0)dfs(board,t,i,j-1);
        board[i][j]=c;
        return;
    }
    vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
        Trie* t=new Trie();
        for(int i=0;i<words.size();i++)
        {
            Trie* cur=t;
            for(int j=0;j<words[i].size();j++)
            {
                if(cur->child[words[i][j]-'a']==nullptr)
                {
                    cur->child[words[i][j]-'a']=new Trie();
                }
                cur=cur->child[words[i][j]-'a'];
            }
            cur->word=words[i];
        }
       
        for(int i=0;i<board.size();i++)
        {
            for(int j=0;j<board[i].size();j++)
            {
                dfs(board,t,i,j);
            }
        }
        return ans;
    }
};

 

 

前缀树模板:

一次建树,多次查询


class Trie {
private:
    bool isEnd;
    Trie* next[26];
public:
    //方法在下面实现
};

void insert(string word) {
    Trie* node = this;
    for (char c : word) {
        if (node->next[c-'a'] == NULL) {
            node->next[c-'a'] = new Trie();
        }
        node = node->next[c-'a'];
    }
    node->isEnd = true;
}

bool search(string word) {
    Trie* node = this;
    for (char c : word) {
        node = node->next[c - 'a'];
        if (node == NULL) {
            return false;
        }
    }
    return node->isEnd;
}

 

posted @ 2022-11-22 21:25  zzzlight  阅读(57)  评论(0编辑  收藏  举报