1 基础知识
trie树算法,也叫作字典树算法。
用处:用来高效存储和查找字符串集合的数据结构。
(一)
定义变量。
const int N = 1e5 +10;
int son[N][26], cnt[N], idx;
char str[N];
(二)
插入操作。
void insert(char* str) {
int p = 0;
for (int i = 0; str[i]; ++i) {
int u = str[i] - 'a';
if (!son[p][u]) son[p][u] = ++idx;
p = son[p][u];
}
cnt[p]++;
return;
}
(三)
查询操作。
int query(char* str) {
int p = 0;
for (int i = 0; str[i]; ++i) {
int u = str[i] - 'a';
if (!son[p][u]) return 0;
p = son[p][u];
}
return cnt[p];
}
2 模板
const int N = 1e5 + 10;
int son[N][26], cnt[N], idx;
char str[N];
void insert(char* str) {
int p = 0;
for (int i = 0; str[i]; ++i) {
int u = str[i] - 'a';
if (!son[p][u]) son[p][u] = ++idx;
p = son[p][u];
}
cnt[p]++;
return;
}
int query(char* str) {
int p = 0;
for (int i = 0; str[i]; ++i) {
int u = str[i] - 'a';
if (!son[p][u]) return 0;
p = son[p][u];
}
return cnt[p];
}
3 工程化
class Trie {
public:
Trie(int n) {
this->n = n;
son.resize(n, vector<int>(26, 0));
cnt.resize(n, 0);
idx = 0; //注意0表示根结点,也表示空结点。
}
Trie(int n, int m) {
this->n = n;
this->m = m;
son.resize(n, vector<int>(m, 0));
cnt.resize(n, 0);
idx = 0; //注意0表示根结点,也表示空结点。
}
void insert(string str) {
int p = 0;
for (int i = 0; i < str.size(); ++i) {
int u = str[i] - 'a';
if (!son[p][u]) son[p][u] = ++idx;
p = son[p][u];
}
cnt[p]++;
return;
}
int query(string str) {
int p = 0;
for (int i = 0; i < str.size(); ++i) {
int u = str[i] - 'a';
if (!son[p][u]) return 0;
p = son[p][u];
}
return cnt[p];
}
private:
int n;
int m;
int idx;
vector<vector<int>> son;
vector<int> cnt;
};
4 训练
题目1:100268最长公共后缀查询
python3代码如下,
class Solution:
def stringIndices(self, a: List[str], b: List[str]) -> List[int]:
res = []
mi = inf
tmp = -1
for i, w in enumerate(a):
if len(w) < mi:
mi = len(w)
tmp = i
trie = {}
for i, w in enumerate(a):
w = w[::-1]
cur = trie
for c in w:
if c not in cur:
cur[c] = {}
cur = cur[c]
if "#" not in cur:
cur["#"] = (i, len(w))
elif len(w) < cur["#"][1]:
cur["#"] = (i, len(w))
res = []
for w in b:
w = w[::-1]
cur = trie
ans = tmp
for c in w:
if c not in cur:
res.append(ans)
break
else:
cur = cur[c]
ans = cur["#"][0]
else:
res.append(ans)
return res
C++代码如下,
const int N = 5e5 + 10;
int sz, key[N], val[N], ch[N][26];
void init() {
memset(ch[0], 0, sizeof(ch[0]));
key[0] = -1;
sz = 1;
}
void add(string &s, int x) {
int len = s.length();
int u = 0, c;
if (key[0] == -1 || val[0] > len) {
key[0] = x;
val[0] = len;
}
for (int i = len - 1; i >= 0; --i) {
c = s[i] - 'a';
if (!ch[u][c]) {
memset(ch[sz], 0, sizeof(ch[sz]));
key[sz] = -1;
ch[u][c] = sz++;
}
u = ch[u][c];
if (key[u] == -1 || val[u] > len) {
key[u] = x;
val[u] = len;
}
}
}
class Solution {
public:
vector<int> stringIndices(vector<string>& wordsContainer, vector<string>& wordsQuery) {
init();
for (int i = 0; i < wordsContainer.size(); ++i) {
add(wordsContainer[i], i);
}
int n = wordsQuery.size();
vector<int> ret(n);
for (int i = 0; i < wordsQuery.size(); ++i) {
int u = 0, c = 0;
int len = wordsQuery[i].length();
for (int j = len - 1; j >= 0; --j) {
c = wordsQuery[i][j] - 'a';
if (!ch[u][c]) break;
u = ch[u][c];
}
ret[i] = key[u];
}
return ret;
}
};
题目2: