题解0013:字典树模板(洛谷)
题目链接:https://www.luogu.com.cn/problem/P8306
题目描述:给定 n 个模式串和 m 次询问,每次询问给定一个文本串,请回答这个文本串是多少个模式串的前缀。
题目思路:
如图,我们可以建立一个这样的树,并从里面查出字符串,这就是字典树。
(字符串要在线上而不是根节点)
当然,这里面的字符要用数字代替,同一个字符编码相同。
我们还要给每个根节点赋值,就是输入字符的顺序。
上图就是依次将 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 }
完美结束!
分类:
c++刷题
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现