题解0013:字典树模板(洛谷)

题目链接:https://www.luogu.com.cn/problem/P8306

题目描述:给定 个模式串和 次询问,每次询问给定一个文本串,请回答这个文本串是多少个模式串的前缀。

题目思路:

如图,我们可以建立一个这样的树,并从里面查出字符串,这就是字典树。

(字符串要在线上而不是根节点)

当然,这里面的字符要用数字代替,同一个字符编码相同。

我们还要给每个根节点赋值,就是输入字符的顺序。

上图就是依次将 come、time、title、cat、term、can这几个字符存入到字典树的图像。

上代码:

复制代码
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int trie[3000001][65],sum[3000001],n,m,tot=0;//trie的第二个数范围不能太大,可能报错 
 4 string a;
 5 int getnum(char x){//压缩ascal码 
 6     if(x>='A'&&x<='Z')
 7         return x-'A';
 8     else if(x>='a'&&x<='z')
 9         return x-'a'+26;
10     else
11         return x-'0'+52;
12 } 
13 void Q(){//将字符串存入字典树 
14     int as=a.size(); 
15     int root=0;//根节点 
16     for(int i=0;i<as;i++){
17         int id=getnum(a[i]);//字符串的线 
18         if(!trie[root][id]){
19             trie[root][id]=++tot;//如果前面没数,插入 
20         }
21         root=trie[root][id];//根节点下移 
22         sum[root]++;//存到某节点的前缀数++(递推思路) 
23     }
24 }
25 int P(){//查询 
26     int as=a.size(); 
27     int root=0;
28     for(int i=0;i<as;i++){
29         int id=getnum(a[i]);
30         if(!trie[root][id]){//如果前面没数,直接pass 
31             return 0;
32         }
33         root=trie[root][id]; 
34     }
35     return sum[root];//如果找到,直接返回该点前缀数  
36 }
37 int main(){
38     int t;
39     cin>>t;
40     while(t--){
41         for(int i=0;i<=tot;i++){
42             for(int j=0;j<=122;j++){
43                 trie[i][j]=0;
44             }
45         }
46         for(int i=0;i<=tot;i++){
47             sum[i]=0;
48         }//用for循环卡数值清空数组,如果用memset可能空间超限 
49         tot=0;
50         cin>>n>>m;
51         while(n--){
52             cin>>a;
53             Q();
54         }
55         while(m--){
56             cin>>a;
57             cout<<P()<<endl;
58         }
59     }    
60 }
复制代码

完美结束!

 

posted @   uf0_金币灰黄^w.h  阅读(68)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示