一. 基本结构
class Tree {
public:
bool isWord;
vector<Tree*> v;
/** Initialize your data structure here. */
Trie() {
isWord = false;
v.resize(26); //元素个数 全体小写字母26个
}
};
1 需要返回单词string
class Tree {
public:
bool isWord;
string word;
vector<Tree*> v;
Tree() {
isWord = false;
word = "";
v.resize(26);
}
};
2 记录位置idx
class Tree{
public:
bool isWord;
int idx;
vector<Tree*> v;
Tree() {
isWord = false;
idx = -1;
v.resize(52);
}
};
3 记录当前最小值minv
class Tree {
public:
bool isEnd;
vector<Tree*> v;
int minv;
Tree() {
isEnd = false;
v.resize(2);
minv = INT_MAX;
};
};
4 记录动态出现次数heat
class Tree {
public:
bool isWord;
vector<Tree*> v;
string word;
int heat;
Tree() {
isWord = false;
v.resize(27);
heat = -1;
}
};
二. 常用方法
1 插入
void insert(Tree* t, const string &s) {
for(char c : s) {
if(!t->v[c - 'a'])
t->v[c - 'a'] = new Tree();
t = t->v[c - 'a'];
}
t->isWord = true;
//t->word = s; // 需要返回单词string时
//t->idx = idx; // 需要记录位置idx时
}
2 搜索
(1)是否存在
bool search(string word) {
Trie* t = this;
for(char c : word) {
if(!t->v[c - 'a'])
return false;
t = t->v[c - 'a'];
}
return t->isWord;
}
(2)各种DFS 略
三. 特殊应用
1 最大异或
int至多32位,按位(0、1)组成字典树
class Tree {
public:
vector<Tree*> v;
Tree(): v(2){};
static void insert(Tree* t, int n, int L) {
int p = 1 << (L - 1); //使用位与逐位插入
while(p > 0) {
int index = (p & n) ? 0 : 1;
if(!t->v[index]) {
t->v[index] = new Tree();
}
t = t->v[index];
p = p >> 1;
}
}
};
2 前缀+后缀搜索
引入#作为前缀后缀中间过渡
插入时对每个字符串按(所有可能的)位分割,插入(前缀 + # + 后缀)
class Tree {
public:
bool isWord;
vector<Tree*> v;
int weight;
Tree() {
isWord = false;
v.resize(27);
weight = -1;
}
};
WordFilter(vector<string>& words) {
this->root = new Tree();
for(int k = 0; k < words.size(); k++) {
string word = words[k];
for(int i = 0; i < word.size(); i++) {
string suffix = word.substr(i);
string tmp = suffix + "#" + word;
insert(this->root, tmp, k);
}
}
}
3 回文对
查找使words[i]、words[j]组合称为回文串的回文对,使用记录idx的字典树
反序查找匹配回文串
vector<vector<int>> palindromePairs(vector<string>& words) {
tree.emplace_back(node());
int n = words.size();
for(int i = 0; i < n; i++)
insert(words[i], i);
vector<vector<int>> ret;
for(int i = 0; i < n; i++){
int m = words[i].size();
for(int j = 0; j <= m; j++){
if(isPalindrome(words[i], j, m - 1)){
int left_id = findWord(words[i], 0, j - 1);
if(left_id != -1 && left_id != i)
ret.push_back({i, left_id});
}
if(j && isPalindrome(words[i], 0, j - 1)){
int right_id = findWord(words[i], j, m - 1);
if(right_id != -1 && right_id != i)
ret.push_back({right_id, i});
}
}
}
return ret;
}