字典树(Trie树)
使用情况:用在找出某单词是多少个单词的前缀
理解思想:利用字符串的公共前缀来减少查询时间
树图:单词ac ak day dad fall fine 构成的字典树
模板题Gym - 102020D
题目意思:给你一些单词,然后每个字母对应着手机上九宫格打字的数字,给你一些数字串,问你数字串是多少个单词对应数字串的前缀。
字典树思路:把单词转化为数字,就是一道裸字典树。字典树主要是插入和查找两个函数。插入的时候,每次从字典树的根节点开始找看看是否有前缀一样的,直到前缀一样的部分结束,就建立了新的结点。查找的时候,从根节点开始找,找到需要匹配串的相同的最后一个点,返回对应的个数即可。
代码:
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <cstdlib>
#include <map>
#include <queue>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
typedef long long ll;
const int maxn=1e6+6;
int tree[maxn][12]={0};
int sum[maxn]={0};
char s[maxn];
int tot;
void insert_()
{
int len=strlen(s);
int root=0;
for(int i=0;i<len;i++)
{
int id;
//根据九宫格输入把单词变成数字串
if(s[i]>='a'&&s[i]<='c')
id=2;
else if(s[i]>='d'&&s[i]<='f')
id=3;
else if(s[i]>='g'&&s[i]<='i')
id=4;
else if(s[i]>='j'&&s[i]<='l')
id=5;
else if(s[i]>='m'&&s[i]<='o')
id=6;
else if(s[i]>='p'&&s[i]<='s')
id=7;
else if(s[i]>='t'&&s[i]<='v')
id=8;
else if(s[i]>='w'&&s[i]<='z')
id=9;
if(!tree[root][id])tree[root][id]=++tot;//赋予编号,方便记录sum
sum[tree[root][id]]++;
root=tree[root][id];
}
}
int find_()
{
int len=strlen(s);
int root=0;
for(int i=0;i<len;i++)
{
int id=s[i]-'0';
if(!tree[root][id])return 0;
root=tree[root][id];
}
return sum[root];
}
int main()
{
int n,q;
scanf("%d%d",&n,&q);
tot=0;
while(n--)
{
scanf("%s",s);
insert_();
}
while(q--)
{
scanf("%s",s);
printf("%d\n",find_());
}
return 0;
}