Trie
Trie(前缀树)用来保存字符串集合。
这个树的根结点ID为0,其余结点ID为从1开始的正整数。
\(ch[i][j]\)表示结点\(i\)的边为\(j\)的子结点的编号(不存在则为0),例如:\(ch[0][A]=5,ch[1][A]=0\)。
S表示字符集的大小,当字符集为全体小写字母时\(S=26\)。
插入和查询的时间复杂度均为\(O(n)\)(n是单词的长度)。由于英语单词一般不会太长,所以在特定情况下Trie比Map高效。

#define idx(c) c - 'a';
const int N = 100, S = 26;
struct Trie {
int ch[N][S], val[N], sz;
Trie() {
memset(ch, 0, sizeof(ch));
memset(val, 0, sizeof(val));
sz = 0;
}
void insert(string s, int v) {
int p = 0;
for(int i = 0; i < s.length(); i++) {
int c = idx(s[i]);
if(!ch[p][c]) ch[p][c] = ++sz;
p = ch[p][c];
}
val[p] = v;
}
int find(string s) {
int p = 0;
for(int i = 0; i < s.length(); i++) {
int c = idx(s[i]);
if(!ch[p][c]) return 0;
p = ch[p][c];
}
return val[p];
}
};
例题:洛谷P2580
https://www.luogu.com.cn/problem/P2580
#include<bits/stdc++.h>
using namespace std;
#define idx(c) c - 'a';
const int N = 500010, S = 26;
struct Trie {
int ch[N][S], val[N], sz;
Trie() {
memset(ch, 0, sizeof(ch));
memset(val, 0, sizeof(val));
sz = 0;
}
void insert(string s, int v) {
int p = 0;
for(int i = 0; i < s.length(); i++) {
int c = idx(s[i]);
if(!ch[p][c]) ch[p][c] = ++sz;
p = ch[p][c];
}
val[p] = v;
}
int find(string s) {
int p = 0;
for(int i = 0; i < s.length(); i++) {
int c = idx(s[i]);
if(!ch[p][c]) return 0;
p = ch[p][c];
}
if(val[p]) val[p]++;
return val[p];
}
};
int n, m;
string s;
Trie t;
int main() {
cin >> n;
while(n--) {
cin >> s;
t.insert(s, 1);
}
cin >> m;
while(m--) {
cin >> s;
int c = t.find(s);
if(!c) cout << "WRONG\n";
else if(c - 2) cout << "REPEAT\n";
else cout << "OK\n";
}
}

浙公网安备 33010602011771号