字典树模板以及字典树的小应用
(昨天的栈太恶心了只能靠一些模板但是却不能够理解,先放一下)
今天的字典树主要是解决了一些查找和存入的问题。但是目前我还是不能理解和哈希的主要区别,可能字典树比较稳定相对来说比较快,但是快的代价使用内存换的
int trie[maxn][26]; int mark[maxn]; int cnt[maxn]; int tot=1; void insert(string a) { int root=0; for(int i=0;i<a.length();i++) { int id=a[i]-'a'; if(!trie[root][id]) trie[root][id]=tot++; root=trie[root][id]; cnt[root]++; } mark[root]=true; } int find(string a) { int root=0; for(int i=0;i<a.length();i++) { int id=a[i]-'a'; if(!trie[root][id]) return 0; root=trie[root][id]; } return cnt[root]; }
主要的板子使用,对这个板子的理解也就是每一层都有26个字母,刚开始经过时给予不同的值标记之前来过,并且对每个单词的末尾进行一次标记。
例题分析
C - What Are You Talking About
题目不复制了,题意大概是给定一串字符然后去表示另外一串字符最后输出
我刚开始使用的是map的做法,ac了之后又去想了一下如果我用字典树去写这一道题目会怎么样。
其主要思想是不变的,也就是说,对于一个字符串对应的一个数字再去对应一个字母。
这个时候root就可以充当这个字母了
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 #include <cmath> 6 #include <map> 7 #include <stack> 8 #include <vector> 9 using namespace std; 10 const int maxn = 5e5+10; 11 bool mark[maxn]; 12 int dire[maxn][26]; 13 int tot=1; 14 char zf[maxn][15]; 15 int root; 16 char bbb[maxn]; 17 void insert(char *a,string b) 18 { 19 root=0; 20 for(int i=0;i<b.length();i++) 21 { 22 int id=b[i]-'a'; 23 if(!dire[root][id]) dire[root][id]=tot++; 24 root=dire[root][id]; 25 } 26 mark[root]=true; 27 strcpy(zf[root],a); 28 } 29 int find(string a) 30 { 31 root=0; 32 for(int i=0;i<a.length();i++) 33 { 34 int id=a[i]-'a'; 35 if(!dire[root][id]) return 0; 36 root=dire[root][id]; 37 } 38 return mark[root]; 39 } 40 int main() 41 { 42 string a,b; 43 cin>>a; 44 while(scanf("%s",bbb)) 45 { 46 if(strcmp(bbb,"END")==0) break; 47 cin>>b; 48 //cout<<bbb<<" "<<b<<endl; 49 insert(bbb,b); 50 //cout<<zf[root]<<endl; 51 } 52 cin>>a; 53 getchar(); 54 while(getline(cin,a)) 55 { 56 if(a=="END") break; 57 //cout<<a; 58 b=""; 59 for(int i=0;i<a.length();i++) 60 { 61 if(a[i]>='a'&&a[i]<='z') b+=a[i]; 62 else 63 { 64 //cout<<b<<" "<<find(b)<<endl; 65 //cout<<b<<a[i]; 66 if(find(b)) printf("%s",zf[root]); 67 else cout<<b; 68 //cout<<root; 69 cout<<a[i]; 70 b=""; 71 } 72 } 73 printf("\n"); 74 } 75 return 0; 76 }
接下来这个是使用map的方法做的
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> #include <map>; using namespace std; string a,b; map<string,string>mp; int main() { cin>>a; while(cin>>a) { if(a=="END") break; cin>>b; mp[b]=a; //cout<<a<<" "<<b<<endl; } cin>>a; getchar(); while(getline(cin,a)) { if(a=="END") break; //cout<<a<<endl; b=""; for(int i=0;i<a.length();i++) { if(a[i]>='a'&&a[i]<='z') { b+=a[i]; } else { if(mp[b]!="") cout<<mp[b]; else cout<<b; cout<<a[i]; b=""; } } printf("\n"); } return 0; }
总体来说肯定是map更加简单点,但是如果数据再大一点,map时间和空间肯定都是过不了的。
D - 单词数
这一题比较简单,主要是让我学到了一点点sstream的用法
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> #include <map> #include <stack> #include <vector> #include <sstream> using namespace std; const int maxn=1e5+10; int tire[maxn][26]; bool mark[maxn]; int root=0; int tot=1; int cnt=0; void insert(string a) { root=0; for(int i=0;i<a.length();i++) { int id=a[i]-'a'; if(!tire[root][id]) tire[root][id]=tot++; root=tire[root][id]; } if(!mark[root]) { cnt++; } mark[root]=true; } void init() { cnt=0; tot=1; memset(mark,0,sizeof mark); memset(tire,0,sizeof tire); } int main() { string a,p; while(getline(cin,a)) { init(); //cout<<a; if(a=="#") break; stringstream ss(a); while(ss>>p) { insert(p); } cout<<cnt<<endl; } return 0; }
E - Intelligent IME
这一题我觉得还是比较有意思的。
题目就是给一串数字,然后通过那个输入法去输入这串数字,最后查询这串数字可以被用到几次
u1s1,因为数字串是最后被查询的,因此数字串可以放到后面的find来使用,于是就要对下面的字符串做出一定的处理,将字符串转换成数字insert之后然后在进行查询就可以轻松加愉快的写出来了
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> #include <map> #include <stack> #include <vector> #include <sstream> using namespace std; const int maxn=1e5+10; char zf[]={"22233344455566677778889999"}; int tire[maxn][10]; int mark[maxn]; char zf1[5010][10]; char test[10]; int root; int tot=1; void insert(string a) { root=0; for(int i=0;i<a.length();i++) { int id1=a[i]-'a'; // cout<<id1<<endl; int id=(int)zf[id1]-48; //cout<<id<<endl; if(!tire[root][id]) tire[root][id]=tot++; root=tire[root][id]; mark[root]++; } } int find(char *zf1) { root=0; int len=strlen(zf1); for(int i=0;i<len;i++) { int id=zf1[i]-'0'; if(!tire[root][id]) return 0; root=tire[root][id]; } return mark[root]; } void init() { tot=1; root=0; memset(tire,0,sizeof tire); memset(mark,0,sizeof mark); } int main() { string a; int t; cin>>t; int n,m; //cout<<strlen(zf)<<endl; while(t--) { init(); scanf("%d %d",&n,&m); for(int i=1;i<=n;i++) scanf("%s",zf1[i]); //for(int i=1;i<=n;i++) printf("%s\n",zf1[i]); for(int i=1;i<=m;i++) { cin>>a; insert(a); } for(int i=1;i<=n;i++) { int num=find(zf1[i]); cout<<num<<endl; } } return 0; }
确实自己还是一条懒狗,但是还是没有太大动力啊,回校能好好加油冲冲冲了(争取大二就能摸到牌子吧,规划好自己ACMer的生涯,也规划好除了ACM之外的东西,快乐一点才是最重要的)

浙公网安备 33010602011771号