-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathProblem_0212_findWords.cc
151 lines (140 loc) · 3.23 KB
/
Problem_0212_findWords.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#include <algorithm>
#include <iostream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include "UnitTest.h"
using namespace std;
class Solution
{
private:
class Node
{
public:
int pass;
int end;
unordered_map<int, Node *> nexts;
Node()
{
pass = 0;
end = 0;
}
};
public:
// 根据目标单词构造字典树
void fillWord(Node *node, string &word)
{
node->pass++;
for (auto &c : word)
{
int index = c;
if (!node->nexts.count(index))
{
node->nexts.emplace(index, new Node());
}
node = node->nexts.at(index);
node->pass++;
}
node->end++;
}
int process(vector<vector<char>> &board, int i, int j, string &path, Node *cur, vector<string> &ans)
{
char c = board[i][j];
if (c == 0)
{
// 这个位置之前走过
return 0;
}
int index = c;
if (!cur->nexts.count(index) || cur->nexts.at(index)->pass == 0)
{
// 没有路,或者这条路上最终的字符串之前加入过结果里面
return 0;
}
cur = cur->nexts.at(index);
// 当前字符加入路径
path.push_back(c);
// 从i和j位置出发,后续一共搞定了多少答案
int fix = 0;
if (cur->end > 0)
{
// 当我来到i j位置,如果决定不往后走了。是不是已经搞定了某个字符串了
ans.push_back(path);
cur->end--;
fix++;
}
// 往上、下、左、右,四个方向尝试
board[i][j] = 0;
if (i > 0)
{
fix += process(board, i - 1, j, path, cur, ans);
}
if (i < board.size() - 1)
{
fix += process(board, i + 1, j, path, cur, ans);
}
if (j > 0)
{
fix += process(board, i, j - 1, path, cur, ans);
}
if (j < board[0].size() - 1)
{
process(board, i, j + 1, path, cur, ans);
}
// 回溯
board[i][j] = c;
path.pop_back();
cur->pass -= fix;
return fix;
}
vector<string> findWords(vector<vector<char>> &board, vector<string> &words)
{
Node *root = new Node();
unordered_set<string> set;
for (auto &word : words)
{
if (!set.count(word))
{
fillWord(root, word);
set.emplace(word);
}
}
vector<string> ans;
string path;
for (int i = 0; i < board.size(); i++)
{
for (int j = 0; j < board[0].size(); j++)
{
// 枚举在board中的所有位置
// 每一个位置出发的情况下,答案都收集
process(board, i, j, path, root, ans);
}
}
return ans;
}
};
bool isVectorEqual(vector<string> a, vector<string> b)
{
std::sort(a.begin(), a.end());
std::sort(b.begin(), b.end());
return a == b;
}
void testFindWords()
{
Solution s;
vector<vector<char>> b1 = {{'o', 'a', 'a', 'n'}, {'e', 't', 'a', 'e'}, {'i', 'h', 'k', 'r'}, {'i', 'f', 'l', 'v'}};
vector<vector<char>> b2 = {{'a', 'b'}, {'c', 'd'}};
vector<string> w1 = {"oath", "pea", "eat", "rain"};
vector<string> w2 = {"abcb"};
vector<string> o1 = {"eat", "oath"};
vector<string> o2;
EXPECT_TRUE(isVectorEqual(o1, s.findWords(b1, w1)));
EXPECT_TRUE(isVectorEqual(o2, s.findWords(b2, w2)));
EXPECT_SUMMARY;
}
int main()
{
testFindWords();
return 0;
}