LeetCode 212. 單詞搜索 II (DFS+字典樹)

單詞搜索 II
它的簡單版的功能是解決一個單詞存在與否,如果此題直接套用這個函數,也是可行的,不過時間複雜度太高,O(mnlen(str)size)O(m*n*len(str)*size)
具體的來看,在一開始的搜索框架中,每次都是匹配一個字符串的某一個位置的字符。
如何優化呢?
用字典樹去預存size個字符串,然後對於網格中的某一個節點去看字典樹的這一層有沒有這個字符,如果有,再去看它是不是某個字符串結尾(注意,如果是,不要回溯,繼續往下搜)。這樣,網格中的每一個點只要遍歷一次即可。
時間複雜度:
O(sizelen+mnlen)O(size*len+m*n*len) 如果size很大的話,這個優化是非常明顯的。

const int dx[] = {-1,0,1,0};
const int dy[] = {0,1,0,-1};
class Solution {
    struct Node{
        bool isEnd = false;
        string str = "";
        Node* children[26] = {0};
    };
    Node* root = new Node;
    void insert(const string& s){
        Node* p = root;
        for(char c:s){
            if(!p->children[c-'a']){
                p->children[c-'a'] = new Node;
            }
            p = p->children[c-'a'];
        }
        p->isEnd = true;
        p->str = s;
    }
public:
    unordered_set<string> res;
    vector<string> ans;
    vector<vector<bool>> vis;
    int m,n;
    vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
        m = board.size();
        n = board[0].size();
        vis.resize(m+1,vector<bool>(n+1,false));
        for(string& s:words){
            insert(s);
        }
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                dfs(i,j,root,board);
            }
        }
        for(const string& s:res){
            ans.push_back(s);
        }
        return ans;
    }
    void dfs(int x,int y,Node* p,vector<vector<char>>& board) {
        char c = board[x][y]; 
        Node* pp = p->children[c-'a'];       
        if(pp){
            if(pp->isEnd){
                res.insert(pp->str);
            }
            vis[x][y] = 1;
            for(int k=0;k<4;k++){
                int nx = x+dx[k];
                int ny = y+dy[k];
                if(nx>=0&&nx<m&&ny>=0&&ny<n && !vis[nx][ny]){
                    dfs(nx,ny,pp,board);
                }
            }
            vis[x][y] = 0;
        }
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章