Trie树+HDU1251
Posted jtyyy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Trie树+HDU1251相关的知识,希望对你有一定的参考价值。
一、引入:
先看一道模板题:https://vjudge.net/problem/HDU-1251。
简单!把每个单词的每个前缀提取出来,开个map存一下就行了。
时间复杂度:O(n^2log(n))。T飞了QAQ。
这时Trie树就来帮忙了。
二、正题:
Trie树,也就是字典树(如图,其中包含单词he、her、hi、she)
从根节点到某一标记(涂黑)节点遍历一遍,得到的就是存进Trie树中的一个单词
三、操作
1、insert(插入)
首先我们可以编号每一个节点,在插入一个新的单词str时,设在树上当前节点为s,在新单词中的位置为i,找是否存在s的一个儿子表示str[i]。有,则s跳到这个儿子;没有,则s新开一个儿子,然后跳到这个儿子。
代码如下
void insert(string str) { trie *s=head;//当前节点 int len=str.size(); for(int i=0;i<len;i++) { int id=str[i]-‘a‘+1;//适当的离散可以节省空间 if(s->to[id]==NULL)//s没有表示str[i]的这个儿子 { trie *t=new trie;//新开一个 for(int j=1;j<=26;j++) t->to[j]=NULL; t->count=0; t->ed=0; s->to[id]=t; } s=s->to[id];//s跳到表示str[i]的这个儿子 s->count++; } s->ed=1;//打标迹,表示此处有单词结束(上图中的涂黑的点) }
2、search(查找)
有两种:
1、找该单词是否在字典中
2、找某一字符串为字典中多少单词的前缀
很简单,和建树差不多。设当前被查询的字符串为str,当前节点为s,在字符串上的位置为i。判断s是否有表示str[i]的儿子。没有,显然字典中没有该单词;有,则跳到这个儿子。最后做一点简单的判断就行了。
代码如下
1 bool search1(string str)//问题一 2 { 3 trie *s=head; 4 int len=str.size(); 5 for(int i=0;i<len;i++) 6 { 7 int id=str[i]-‘a‘+1;//建树时怎么离散的现在就怎么离散 8 if(s->to[id]==NULL)//该儿子不存在 9 return 0; 10 s=s->to[id];//跳到该儿子 11 } 12 return s->ed; 13 } 14 int search2(string str)//问题二 15 { 16 trie *s=head; 17 int len=str.size(); 18 for(int i=0;i<len;i++) 19 { 20 int id=str[i]-‘a‘+1; 21 if(s->to[id]==NULL) 22 return 0; 23 s=s->to[id]; 24 } 25 return s->count; 26 }
三、例题:
回到栗子。
明显这里用到了insert和search2。
吐槽这题的输入格式。
不多说,上代码。
1 #include<iostream> 2 #include<cstdlib> 3 #include<cstdio> 4 #include<cmath> 5 #include<cstring> 6 #include<string> 7 #include<algorithm> 8 #include<queue> 9 using namespace std; 10 struct trie 11 { 12 int count; 13 trie *to[27]; 14 }; 15 trie *head; 16 void insert(string str) 17 { 18 trie *t,*s=head; 19 int len=str.size(); 20 for(int i=0;i<len;i++) 21 { 22 int id=str[i]-‘a‘+1; 23 if(s->to[id]==NULL) 24 { 25 t=new trie; 26 for(int j=1;j<=26;j++) 27 t->to[j]=NULL; 28 t->count=0; 29 s->to[id]=t; 30 } 31 s=s->to[id]; 32 s->count++; 33 } 34 } 35 int search(string str) 36 { 37 trie *s=head; 38 int ans=0; 39 int len=str.size(); 40 for(int i=0;i<len;i++) 41 { 42 int id=str[i]-‘a‘+1; 43 if(s->to[id]==NULL) 44 return 0; 45 s=s->to[id]; 46 ans=s->count; 47 } 48 return ans; 49 } 50 int main() 51 { 52 string s,str; 53 head=new trie; 54 for(int i=1;i<=26;i++) 55 { 56 head->to[i]=NULL; 57 head->count=0; 58 } 59 while(1) 60 { 61 getline(cin,s); 62 insert(s); 63 if(s=="") 64 break; 65 } 66 while(getline(cin,str)) 67 cout<<search(str)<<endl; 68 return 0; 69 }
我看其他博客基本上都是用指针,我学的时候看得一头雾水。
为避免这种情况,我上一份不用指针的。(建议不用指针,慢死了)
1 #include<iostream> 2 #include<cstdlib> 3 #include<cstdio> 4 #include<cmath> 5 #include<cstring> 6 #include<string> 7 #include<algorithm> 8 #include<queue> 9 using namespace std; 10 int ch[1000010][26],cnt,cou[1000010]; 11 void insert(string str) 12 { 13 int len=str.size(),s=0; 14 for(int i=0;i<len;i++) 15 { 16 int id=str[i]-‘a‘+1; 17 if(!ch[s][id]) 18 ch[s][id]=++cnt; 19 s=ch[s][id]; 20 cou[s]++; 21 } 22 } 23 int search(string str) 24 { 25 int len=str.size(),s=0; 26 for(int i=0;i<len;i++) 27 { 28 int id=str[i]-‘a‘+1; 29 if(!ch[s][id]) 30 return 0; 31 s=ch[s][id]; 32 } 33 return cou[s]; 34 } 35 int main() 36 { 37 string s,str; 38 while(1) 39 { 40 getline(cin,s); 41 insert(s); 42 if(s=="") 43 break; 44 } 45 while(getline(cin,str)) 46 cout<<search(str)<<endl; 47 return 0; 48 }
以上是关于Trie树+HDU1251的主要内容,如果未能解决你的问题,请参考以下文章