I. Title Description
Given a 2D board and a list of words from the dictionary, find all words in the board.
Each word must is constructed from letters of sequentially adjacent cell, where "adjacent" cells is those horizontally or Vertically neighboring. The same letter cell is used more than once in a word.
For example,
Given words = and ["oath","pea","eat","rain"] board =
[ [‘o‘,‘a‘,‘a‘,‘n‘], [‘e‘,‘t‘,‘a‘,‘e‘], [‘i‘,‘h‘,‘k‘,‘r‘], [‘i‘,‘f‘,‘l‘,‘v‘]]
Return ["eat","oath"] .
Note:
You may assume this all inputs is consist of lowercase letters a-z .
Two. Topic analysis
If you follow the word search method, you must time out.
A widely used method is the use of the dictionary tree, the relevant introduction of the Internet, a simple way to follow a statement, is a word search tree, trie tree, belong to the tree structure, is a hash tree variant. Typical applications are used for statistics, sorting, and saving a large number of strings (but not limited to strings), so it is often used by search engine systems for text frequency statistics. Its advantages are: the use of the common prefix of the string to reduce query time, to minimize the unnecessary string comparison, query efficiency than Hashi.
The specific nature of the search method, etc. can be referred to: http://baike.baidu.com/link?url=BR1qdZ2oa8BIRbgtD6_ Ovsabhzrecdj0mmfntuvpgnjpg3xgjzihyudfalw1pa30-ofusnjrwpsanhng65l-ja
and the specific problem-solving ideas are:
- Store the words you want to find in the dictionary tree trie, use DFS to find them in board, and use the dictionary tree to prune them.
- Each time a word is found, the word is deleted from the dictionary tree.
- The returned results are arranged incrementally in dictionary order.
Three. Sample code
Although the following code uses a dictionary tree to improve DFS, it is still time-consuming to find the algorithm after AC:
#include <iostream>#include <vector>#include <string>#include <algorithm>using namespace STD;classtrienode{ Public: Trienode ()//Constructors{ for(inti =0; I < -; ++i) Next[i] = NULL; End =false; }voidInsertstrings) {if(S.empty ()) {end =true;return; }if(next[s[0] -' A '] = = NULL) next[s[0] -' A '] =NewTrienode (); next[s[0] -' A ']->insert (S.substr (1));//Move right One intercept string s, continue recursive insert}BOOLSearchstringKey) {if(Key.empty ())returnEndif(next[key[0] -' A '] = = NULL)return false;returnnext[key[0] -' A ']->search (Key.substr (1)); }BOOLStartsWith (stringPrefix) {if(Prefix.empty ())return true;if(next[prefix[0] -' A '] = = NULL)return false;returnnext[prefix[0] -' A ']->startswith (Prefix.substr (1)); }Private: Trienode *next[ -];BOOLEnd;};classtri{ Public: Tri () {root =NewTrienode (); }voidInsertstrings) {Root->insert (s);//Call the method of the Trienode class}BOOLSearchstringK) {returnRoot->search (k); }BOOLStartsWith (stringP) {returnRoot->startswith (P); }Private: Trienode *root;};classsolution{ Public: vector<string>Findwords ( vector<vector<char>>& Board, vector<string>& words) {Const intx = Board.size ();Const inty = board[0].size (); for(Autoptr:words) Tree.insert (PTR);//Insert a candidate word into the dictionary tree vector<string>Result for(inti =0; i < x; ++i) { for(intj =0; J < y; ++J) {//used to record the path traversed vector<vector<bool> >The (x, vector<bool>(Y,false)); DFS (board, it,"", I, J, result); } }//The following actions exclude repeated occurrences of the wordSort (Result.begin (), Result.end ()); Result.erase (Unique (Result.begin (), Result.end ()), Result.end ());returnResult }Private: Tri tree;voidDfs vector<vector<char> >&board, vector<vector<bool> >,stringWordintXintY vector<string>&result) {if(X <0|| x >= board.size () | | Y <0|| Y >= board[0].size ())//Out of bounds return;if(Way[x][y])return; Word.push_back (Board[x][y]);if(Tree.search (Word)) result.push_back (word);if(Tree.startswith (Word)) {Way[x][y] =true; DFS (board, it, Word, X +1, y, result); DFS (board, it, Word, X-1, y, result); DFS (board, it, Word, x, y +1, result); DFS (board, it, Word, x, Y-1, result); Way[x][y] =false; } word.pop_back (); }};
Here is an algorithm for using a dictionary tree on the web, which takes time 48ms-56ms:
classTrie { Public: Trie *next[ -];BOOLExist Trie () {Fill_n (Next, -,nullptr); exist =false; } ~trie () { for(inti =0; I < -; ++i)DeleteNext[i]; }voidInsertConst string&t) {Trie *iter = This; for(inti =0; I < t.size (); ++i) {if(Iter->next[t[i]-' A '] ==nullptr) Iter->next[t[i]-' A '] =NewTrie (); ITER = Iter->next[t[i]-' A ']; } iter->exist =true; }};classSolution { Public:intM, N; vector<string>Findwords ( vector<vector<char>>& Board, vector<string>& words) {Trie *trie =NewTrie (); for(Auto&s:words) Trie->insert (s); m = Board.size (); n = board[0].size (); vector<string>RetstringSofar; for(inti =0; I < m; ++i) { for(intj =0; J < N; ++j) {BC (board, RET, Sofar, Trie, I, J); } }returnRet }voidbc vector<vector<char>>&board, vector<string>&ret,string&sofar, Trie *root,intXintY) {if(X <0|| Y <0|| X >= m | | Y >= N | | Board[x][y] = =' + '|| Root = =nullptr)return;if(Root->next[board[x][y]-' A '] ==nullptr)return; root = Root->next[board[x][y]-' A '];Chart =' + '; Swap (T, Board[x][y]); Sofar.push_back (t);if(root->exist) {root->exist =false; Ret.push_back (SOFAR); } BC (Board, RET, Sofar, root, x, Y +1); BC (Board, RET, Sofar, root, x +1, y); BC (Board, RET, Sofar, root, X-1, y); BC (Board, RET, Sofar, root, x, Y-1); Swap (T, Board[x][y]); Sofar.pop_back (); }};
Four. Summary
Learning and using a dictionary tree for the first time is not very familiar, and the code that is written is more expensive to calculate.
Leetcode notes: Word Search II