Leetcode 212. 单词搜索 II 字典树优化dfs

Leetcode 212. 单词搜索 II

题意

给定一个 m x n 二维字符网格 board 和一个单词(字符串)列表 words,找出所有同时在二维网格和字典中出现的单词。

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

示例 1:

img

输入: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:

img

输入: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 中的所有字符串互不相同

题解

首先将所有words插入字典树,这样在dfs搜索的时候就可以进行减枝。

指针版本:

class Solution {
public:
    struct Node {
        int id;
        Node *son[26];
        Node() {
            id = -1;
            for (int i = 0; i < 26; i ++ ) son[i] = NULL;
        }
    }*root;
    unordered_set<int> ids;
    vector<vector<char>> g;
    int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};

    void insert(string& word, int id) {
        auto p = root;
        for (auto c: word) {
            int u = c - 'a';
            if (!p->son[u]) p->son[u] = new Node();
            p = p->son[u];
        }
        p->id = id;
    }

    vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
        g = board;
        root = new Node();
        for (int i = 0; i < words.size(); i ++ ) insert(words[i], i);

        for (int i = 0; i < g.size(); i ++ )
            for (int j = 0; j < g[i].size(); j ++ ) {
                int u = g[i][j] - 'a';
                if (root->son[u])
                    dfs(i, j, root->son[u]);
            }

        vector<string> res;
        for (auto id: ids) res.push_back(words[id]);
        return res;
    }

    void dfs(int x, int y, Node* p) {
        if (p->id != -1) ids.insert(p->id);
        char t = g[x][y];
        g[x][y] = '.';
        for (int i = 0; i < 4; i ++ ) {
            int a = x + dx[i], b = y + dy[i];
            if (a >= 0 && a < g.size() && b >= 0 && b < g[0].size() && g[a][b] != '.') {
                int u = g[a][b] - 'a';
                if (p->son[u]) dfs(a, b, p->son[u]);
            }
        }
        g[x][y] = t;
    }
};

数组版本

class Solution {
public:
   int son[100005][30], idx, id[100005], n, m;
   vector<vector<char>> g;
   unordered_set<int> ids;
   int dx[4] = {0, 0, -1, 1}, dy[4] = {1, -1, 0, 0};
   void insert(string s, int i){
       int p = 0;
       
       for(char x : s){
           int u = x - 'a';
           if(!son[p][u]) son[p][u] = ++idx;
           p = son[p][u];
       }
       id[p] = i;
   }
   void dfs(int x, int y, int p){
       
       if(id[p] != -1) ids.insert(id[p]);
       char t = g[x][y];
       g[x][y] = '.';
       for(int i = 0; i < 4; i++){
           int a = x + dx[i], b = y + dy[i];
           if(a >= 0 && a < n && b >= 0 && b < m && g[a][b] != '.'){
               int u = g[a][b] - 'a';
               if(son[p][u]){
                   dfs(a, b, son[p][u]);
               }
           }
       }
       
       g[x][y] = t;
   }
   vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
       
      memset(id, -1, sizeof(id));
      for(int i = 0; i < words.size(); i++){
          insert(words[i], i);
      }
      g = board;
       n = g.size(), m = g[0].size();
       
       
       for(int i = 0; i < n; i++){
           for(int j = 0; j < m; j++){
               int u = g[i][j] - 'a';
              
               if(son[0][u])
                   dfs(i, j, son[0][u]);
           }
       }
       vector<string> res;
       for(int id : ids){
           res.push_back(words[id]);
       }
       return res;
   }
};
posted @ 2021-09-21 16:21  pxlsdz  阅读(293)  评论(0编辑  收藏  举报