题意: 给出一些单词, 再询问一些单词是之前那些单词的多少个的前缀.
字典树:
x表示整个字典树的第几个节点, c表示这个字符串第x个节点处是c字符. trie表示下一个字符是几号节点.
每个节点只能由一个节点的某个字符得到, 每个节点的每个字符都有可能连接到一个节点, 所以这是一个树.
当这个树满时, 空间是26^len.
对于这个题, 每个节点储存走到过这个节点的上一节点的字符串个数.(如果在本节点存的话, 只有1维无法判断最后一个字符是否相同, 而开2维会MLE且没必要)
代码:
#include<bits/stdc++.h>
using namespace std;
void debug_out() {
cerr << '\n';
}
template<typename T, typename ...R>
void debug_out(const T &f, const R &...r) {
cerr << f << " ";
debug_out(r...);
}
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]: ", debug_out(__VA_ARGS__);
typedef long long ll;
int trie[(int)4e5][26];
int cnt[(int)4e5];
int k = 1;
void insert(char *x) {
int pos = 0;
int lenX = strlen(x);
for (int i = 0; i < lenX; ++i) {
int now = x[i] - 'a';
if (!trie[pos][now]) {
trie[pos][now] = k;
k++;
}
pos = trie[pos][now];
cnt[pos]++;
}
}
int search(char *x) {
int pos = 0;
int lenX = strlen(x);
for (int i = 0; i < lenX; ++i) {
int now = x[i] - 'a';
if (!trie[pos][now]) {
return 0;
} else {
pos = trie[pos][now];
if(i==lenX-1)
return cnt[pos];
}
}
}
int main() {
char a[15];
while (gets(a) && strlen(a)!=0) {
insert(a);
}
// debug(k);
// for(int i=0;i<k;i++){
// for(int j=0;j<26;j++){
// if(cnt[i][j]!=0)
// printf("[%d %c] %d ",i,j+'a',cnt[i][j]);
// }
// puts("");
// }
while (gets(a)) {
printf("%d\n", search(a));
}
return 0;
}
有一个问题: 字典树到底怎么算空间?