(力扣每日一题)单词搜索 II(字典树+DFS)

题目链接:力扣

大意:给出一个m*n的二维字符网格和一个字符串列表,定义在网格中出现的单词为,由相邻单元格的字母组成,问有多少个单词既出现在字符串列表,又出现在网格内。

思路:

  • 首先网格中的字符串可以由DFS得到,但是如何判断是否出现在字符串列表中呢,如果直接枚举判断的话,O(n*m*words.size()),T掉了。
  • 优化,引入字典树,字典树可以存储以某一段字符串为前缀的字符有多少个,将字符串列表中的单词插入到字典树中,并且在插入完成后用一个变量val存储字典树节点的值。
  • 剪枝,对于DFS得到的每个字符串在字典树上判断是否存在以这个字符串为前缀的字符串,如果没有,那就没必要再搜索下去了。还有就是判断val和当前搜到的字符串是否相等,如果相等,则加入ans。
  • 优化,对于常规的字典树,我们会单独写一个find函数去查找,但是在这还是会T,所以在搜的时候,同时字典树也进行搜索,其实就是在dfs中增加了pos,pos用于找到字典树中当前节点的下一个节点,这样上述操作都可以在dfs中完成了。

Code

class Solution {
public:
    int dir[4][2] = {1,0,-1,0,0,1,0,-1};
    int f[500005][30] = {0},tot = 0;
    string val[50005];
    vectorans;
    settmp;
    int vis1[30005] = {0};
    int vis[15][15] = {0};
    int n,m,wn;
    void insert(string &s) {
        int pos = 0;
        for(int i = 0; i < s.size(); i++)  {
            if(!f[pos][s[i]-'a']) f[pos][s[i]-'a'] = ++tot;
            pos = f[pos][s[i]-'a'];
            //num[pos]++;
        }
        val[pos] = s;
    }

    void dfs(vector>& board,vector& words,int sx,int sy,string s,int pos) {
        int idx = board[sx][sy]-'a';
        if(!f[pos][idx]) return;
        if(val[f[pos][idx]] == s) tmp.insert(s);
        //cout << s << endl;
        for(int i = 0; i < 4; i++) {
            int dx = sx+dir[i][0];
            int dy = sy+dir[i][1];
            if(dx < 0 || dx >= n || dy < 0 || dy >= m || vis[dx][dy]) continue;
            vis[dx][dy] = 1;
            dfs(board,words,dx,dy,s+board[dx][dy],f[pos][idx]);
            vis[dx][dy] = 0;
        }
    }

    vector findWords(vector>& board, vector& words) {
        n = board.size(),m = board[0].size(),wn = words.size();
        for(int i = 0; i < wn; i++) {
            insert(words[i]);
        }
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < m; j++) {
                vis[i][j] = 1;
                string ss = "";
                ss += board[i][j];
                dfs(board,words,i,j,ss,0);
                vis[i][j] = 0;
            }
        }
        //cout << find("oath") << endl;
        for(auto &it:tmp) ans.push_back(it);
        return ans;
    }
};

你可能感兴趣的:(每日一题,leetcode,c++,算法)