字典树模板以及字典树的小应用

(昨天的栈太恶心了只能靠一些模板但是却不能够理解,先放一下)

今天的字典树主要是解决了一些查找和存入的问题。但是目前我还是不能理解和哈希的主要区别,可能字典树比较稳定相对来说比较快,但是快的代价使用内存换的

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

 HDU - 1075

题目不复制了,题意大概是给定一串字符然后去表示另外一串字符最后输出

我刚开始使用的是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 - 单词数

 HDU - 2072

这一题比较简单,主要是让我学到了一点点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

 HDU - 4287 

这一题我觉得还是比较有意思的。

题目就是给一串数字,然后通过那个输入法去输入这串数字,最后查询这串数字可以被用到几次

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之外的东西,快乐一点才是最重要的)

posted @ 2021-02-25 19:38  Treasure-  阅读(53)  评论(0)    收藏  举报