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的主要内容,如果未能解决你的问题,请参考以下文章

HDU 1251 Trie树模板题

HDU1251 统计难题 trie树

HDU 1251 统计难题 (字符串-Trie树)

字典树(trie树)学习总结(例题讲解:POJ2001,HDU1251,HDU4825)

hdu 1251 统计难题(字典树)

HDU - 1251 统计难题(trie树)