单词搜索 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;
}
}
};