Word Search II

本文介绍了一种在二维字符网格中寻找字典中所有单词的方法。通过使用深度优先搜索(DFS)结合字典树(Trie),算法能够高效地从矩阵中识别出所有可能的单词。文章详细解释了算法原理,包括如何构建字典树和如何进行矩阵搜索。
摘要由CSDN通过智能技术生成

Given a 2D board and a list of words from the dictionary, find all words in the board.

Each word must be constructed from letters of sequentially adjacent cell, where "adjacent" cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once in a word.

 

Example:

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

Output: ["eat","oath"]
/* 一个很复杂的大问题: 给定矩形字符阵
 * 只能水平方向或竖直方向移动  求在字典中能搜出来的
 * 显然可以对字典中每个字符走一趟dfs
 * 但是: 字典中某些单词如果有共同前缀
 * 在矩阵中搜索向trie上的非空节点(相当于在trie上深搜)
 * */
struct TrieNode{
    TrieNode* child[26];
    bool isEnd;
    TrieNode():isEnd(false){
        for(int i=0;i<26;i++){
            child[i] = NULL;
        }
    }
};
class Trie{
public:
    TrieNode *root;
    Trie(vector<string> &dicts){
        root = new TrieNode();
        for(string &s : dicts){
            insert(s);
        }
    }
    void delNode(TrieNode *root){
        for(auto &child : root->child){
            if(child)   delNode(child);
        }
        delete(root);
    }
    ~Trie(){
        delNode(root);
    }
    void insert(string &words){
        auto tmp = root;
        for(char &c : words){
            int id = c-'a';
            if(tmp->child[id]==NULL){
                TrieNode *node = new TrieNode();
                tmp->child[id] = node;
            }
            tmp = tmp->child[id];
        }
        tmp->isEnd = true;
    }
    bool find(string &words){
        auto tmp=root;
        for(char &c:words){
          int id = c-'a';
          if(tmp->child[id]==NULL)  return false;
          else tmp = tmp->child[id];
        }
        return tmp->isEnd;
    }
};
class Solution {
public:
    set<string> found;
    int row, col;
    int dx[4]={0, 0, 1, -1};
    int dy[4]={1,-1, 0, 0};
    vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
        // 每个位置对trie树dfs 递归搜索并记录已经得到的结果
        row=board.size(), col=board[0].size();
        Trie *trie = new Trie(words);
        for(int i=0;i<row;i++){
            for(int j=0;j<col;j++){
                dfs(board, "", trie->root, i, j);
            }
        }
        delete(trie);
        vector<string> ret;
        for(auto &s:found)  ret.push_back(s);
        return ret;
    }
    // 注意root指向当前节点的前一个(第一次dfs时 root指向树的根节点 执行一次root->child才到当前节点)
    void dfs(vector<vector<char>>& board, string word, TrieNode *root, int x, int y){
        // 当前位置四个方向没有越界 没有拐回到遍历过的路径上 并且在字典树的路径上存在的点继续dfs
        if(x<0 || x==row || y<0 || y==col || board[x][y]=='#')  return;
        root = root->child[board[x][y]-'a'];
        if(!root)   return;
        word.push_back(board[x][y]);
        if(root->isEnd) found.insert(word);
        char tmp = board[x][y];
        board[x][y]='#';
        for(int i=0;i<4;i++){
            dfs(board, word, root, x+dx[i], y+dy[i]);
        }
        board[x][y]=tmp;
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值