212 单词搜索II

思路:
先将单词插入到前缀树中,然后再DFS一步步去判断下一个要遍历的字符是否存在前缀树中,若存在,则加入中间变量中,若当前遍历的字符序列在字典树中组成一个单词,则加入ans中
不存在,则停止该方向的搜索,因为前缀不存在,则后面DFS生成的单词均以此为前缀,均不存在
在DFS时使用一个set来保存存在于前缀树中的单词,因为遍历时可能会有重复的单词加入,注意DFS时对于vis数组和中间变量的重置。
【212 单词搜索II】最后将自动排序好的set转为vector作为ans返回即可。

class Trie { public: bool is_end; Trie *next[26]; // 单词在a - z之间 Trie() { is_end = false; for(int i = 0; i < 26; ++i) next[i] = nullptr; }void insert(const string& word) { Trie *t = this; for(auto i : word) { if(t->next[i - 'a'] == nullptr) t->next[i - 'a'] = new Trie(); t = t->next[i - 'a']; } t->is_end = true; } }; class Solution { Trie *root; int row, col; int dx[4] = {0, -1, 0, 1}, dy[4] = {1, 0, -1, 0}; set> aws; // 暂存遍历时的存在的单词,可能会有重复元素,去重用set string temp; // 用来存储遍历时生成的中间字符串 vector> vis; // 标记是否访问过 public: Solution(){root = new Trie(); }void DFS(int i, int j, const vector>& board, const Trie *t) { char c = board[i][j]; printf("%c", c); temp.push_back(c); if(t->next[c - 'a'] == nullptr) { temp.pop_back(); // 每次生成字符串时不能访问这次已经访问过的点,但是下一次开始时能访问与上一次重复的点,要重置vis vis[i][j] = false; return; } vis[i][j] = true; if(t->next[c - 'a']->is_end == true) aws.insert(temp); // 组成前缀树中的一个单词 for(int k = 0; k < 4; ++k) { int I = dx[k] + i, J = dy[k] + j; if(I >= 0 && I < row && J >= 0 && J < col && vis[I][J] == false) DFS(I, J, board, t->next[c - 'a']); } // 运行到这里重置vis和temp vis[i][j] = false; temp.pop_back(); }vector> findWords(vector>& board, vector>& words) { for(auto s : words) root->insert(s); // 先将单词插入到前缀树中 row = board.size(), col = board[0].size(); vis.resize(row); for(int i = 0; i < row; ++i) { vis[i].resize(col); fill(vis[i].begin(), vis[i].end(), false); } for(int i = 0; i < row; ++i) // 对整个图DFS for(int j = 0; j < col; ++j) DFS(i, j, board, root); vector> ans(aws.begin(), aws.end()); // set转换为vector return ans; } };

    推荐阅读