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