大致思路:我们可以让字典树的节点记录每一个节点的出现的次数,然后在我们查找的过程中直接查找最后一个字符对应的节点的次数即可。
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int SIZE = 2e6 + 5;
int trie[SIZE][30];
char s[15],t[15];
int cnt[SIZE],tot;
void insert(char *str){
int len = strlen(str),p = 1;
for(int i = 0; i < len; i++){
int ch = str[i] - 'a';
if(trie[p][ch] == 0) trie[p][ch] = ++tot;
cnt[trie[p][ch]]++;
p = trie[p][ch];
}
}
int search(char *str){
int len = strlen(str),p = 1;
for(int i = 0; i < len; i++){
int ch = str[i] - 'a';
p = trie[p][ch];
if(p == 0) return 0;
}
return cnt[p];
}
int main(int argc, char const *argv[])
{
tot = 1;
while(gets(s)) {
if(s[0] == '\0') break;
insert(s);
}
while(~scanf("%s",t)) printf("%d\n", search(t));
return 0;
}
如果这道题理解了我们可以再看看这道题的变式 前缀统计。
做法和上面一道题类似,这道题不一样的是:在字典树的节点中用cnt记录,表示该节点是多少个字符串的末尾节点,在下面的查询过程中累加途径的每个节点的cnt就是最后的答案。
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int SIZE = 2e6 + 5;
int trie[SIZE][30];
char s[SIZE],ss[SIZE];
int cnt[SIZE],tot;
void insert(char *str){
int len = strlen(str),p = 1;
for(int i = 0; i < len; i++){
int ch = str[i] - 'a';
if(trie[p][ch] == 0) trie[p][ch] = ++tot;
p = trie[p][ch];
}
cnt[p]++;
}
int search(char *str){
int len = strlen(str),p = 1;
int sum = 0;
for(int i = 0; i < len; i++){
int ch = str[i] - 'a';
sum += cnt[trie[p][ch]];
p = trie[p][ch];
}
return sum;
}
int main(int argc, char const *argv[])
{
tot = 1;
int n,t;
scanf("%d %d",&n,&t);
while(n--) {
scanf("%s",s);
insert(s);
}
while(t--){
scanf("%s",ss);
printf("%d\n", search(ss));
}
return 0;
}