數據結構~trie樹(字典樹)


1、概述

Trie樹,又稱字典樹,單詞查找樹或者前綴樹,是一種用於快速檢索的多叉樹結構,如英文字母的字典樹是一個26叉樹,數字的字典樹是一個10叉樹。

我理解字典樹是看了這位大佬博客。還不了解字典樹的可以先進去學習一下

https://www.cnblogs.com/TheRoadToTheGold/p/6290732.html

還有這個講了下為什么用字典樹,和其他的相比優缺點在哪

https://www.cnblogs.com/Allen-rg/p/7128518.html

 

現在來個題來更進一步了解字典樹吧 ,嘻嘻-_-

POJ - 2503  Babelfish

 

You have just moved from Waterloo to a big city. The people here speak an incomprehensible dialect of a foreign language. Fortunately, you have a dictionary to help you understand them.

Input

Input consists of up to 100,000 dictionary entries, followed by a blank line, followed by a message of up to 100,000 words. Each dictionary entry is a line containing an English word, followed by a space and a foreign language word. No foreign word appears more than once in the dictionary. The message is a sequence of words in the foreign language, one word on each line. Each word in the input is a sequence of at most 10 lowercase letters.

Output

Output is the message translated to English, one word per line. Foreign words not in the dictionary should be translated as "eh".

Sample Input

dog ogday
cat atcay
pig igpay
froot ootfray
loops oopslay

atcay
ittenkay
oopslay

Sample Output

cat
eh
loops

Hint

Huge input and output,scanf and printf are recommended. 
 
題意:前面有個字典列表,后一個單詞映射到前一個,后面有很多次查詢,輸出單詞映射到的那個單詞,如果沒有輸出eh
思路:因為這題數據比較弱,所以用map映射照樣可以過,在這里我們當是字典樹入門,之前我們用map可以算某個單詞映射到哪個單詞,這個字典樹和map其實
相差不大,但是在求某個前綴的個數的時候,map就要使用多個映射,這個時候字典樹的優勢就來了
我們可以看下代碼
#include<cstdio>
#include<cstring>
using namespace std;
int top=0;
int a[1000001][27];
int sum[1000001];
void insert(char str[])
{
    int root=0;
    for(int i=0;str[i]!='\0';i++)
    {
        int x=str[i]-'a';
        if(!a[root][x])
        {
            a[root][x]=++top;
        }
        sum[a[root][x]]++;
        root=a[root][x];
    }
}
int find(char str[])
{
    int root=0;
    for(int i=0;str[i]!='\0';i++)
    {
        int x=str[i]-'a';
        if(!a[root][x]) return 0;
        root=a[root][x];
    }
    return sum[root];
}
int main()
{
    char str[11];
    while(gets(str)!=NULL)
    {
        if(strlen(str)==0)
        break;
        insert(str);
    }
    while(gets(str)!=NULL)
    {
        printf("%d\n",find(str));
    }
}

解釋:字典樹的一些編號什么的解釋在上兩篇博客中都有講到,我這里就不再解釋,在以上代碼中,我們是使用a數組存放字典樹,sum數組存放了每個點節點的時候的兒子數量,也就是以這個節點下的大分支的數量個數,這樣的話,sum的功能我們就能理解啦,就是sum[k]  ,以1編號到k編號的這個字符串,sum[k]存放的就是這個字符串的一些東西,以上代碼中我們存的是兒子數,所以就是以這個字符串為前綴的數量,這里我們就能想到這個sum數組不止可以存放前綴兒子數,下面講另外一個應用,也就是上面這個題

 

思路:之前我們sum數組我們存的是到這個編號為止的字符串的兒子數,而這個題是說到一個字符串到另外一個字符串的映射,我們就可以想到,一個是一個字符串對應一個整數,一個是一個字符串對應一個字符串,我們是不是只要把那個sum[k]的整數換成字符串就可以了呢,答案是肯定的,當然我這里是預先把那些字符串存了下來,然后sum[k]存的是對應於那個字符串數組的一個編號,下面看代碼

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<string>
#include<map>
#include<algorithm>
using namespace std;
typedef long long ll;
int n,m,top=0;
int sum[100001];
char str[101],s[11];
char c[100001][27];
char dic[100001][11];
void insert(char str[],int cnt)
{
    int root=0;
    for(int i=0;str[i]!='\0';i++)
    {
        int x=str[i]-'a';
        if(!c[root][x]) c[root][x]=++top;
        root=c[root][x];
    }
    sum[root]=cnt;
}
int find(char str[])
{
    int root=0;
    for(int i=0;str[i]!='\0';i++)
    {
        int x=str[i]-'a';
        if(!c[root][x]) return 0;
        root=c[root][x];
    }
    return sum[root];
}
int main()
{
    int cnt=1;
    while(gets(str)!=NULL)
    {
        if(strlen(str)==0) break;
        sscanf(str,"%s %s",dic[cnt++],s);
        insert(s,cnt-1);
    }
    while(gets(str)!=NULL)
    {
        int x=find(str);
        if(x==0) printf("eh\n");
        else printf("%s\n",dic[x]);
    }
}

字典樹可能還有好多騷操作沒學,以后學了之后再更新,23333,^_^


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM