国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【數(shù)據(jù)結(jié)構(gòu)】深刨Trie樹(字典樹)

這篇具有很好參考價(jià)值的文章主要介紹了【數(shù)據(jù)結(jié)構(gòu)】深刨Trie樹(字典樹)。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

一、什么是字典樹?

Trie 樹,也叫“字典樹”。顧名思義,它是一個(gè)樹形結(jié)構(gòu)。它是一種專門處理字符串匹配的數(shù)據(jù)結(jié)構(gòu),用來解決在一組字符串集合中快速查找某個(gè)字符串的問題。

Trie 樹的本質(zhì),就是利用字符串之間的公共前綴,將重復(fù)的前綴合并在一起。
舉個(gè)例子,現(xiàn)在我們要存儲一些字符串。
【數(shù)據(jù)結(jié)構(gòu)】深刨Trie樹(字典樹)

1?? 只要前綴相同的我們就不需要兩個(gè)節(jié)點(diǎn)來存儲,但是要注意ABCD和ATCD這兩個(gè)字符串從B和T就分開了,所以后面的CD就不會存到一起。
2?? 有可能一個(gè)字符串是另一個(gè)字符串的前綴。所以我們需要一個(gè)變量來標(biāo)志一個(gè)字符串的結(jié)尾,也能標(biāo)識有多少個(gè)這個(gè)字符串。

二、字典樹的相關(guān)操作

2.1 插入

const int N = 1e6 + 10;
int son[N][26];// 記錄下一個(gè)節(jié)點(diǎn)在第幾層
int cnt[N];// 標(biāo)識字符串結(jié)尾
int idx;// 記錄下一個(gè)要存節(jié)點(diǎn)的層數(shù)

son數(shù)組的作用是記錄儲存子節(jié)點(diǎn)的位置,而26則代表了26個(gè)字符,類似于26叉樹。
cnt的作用就是標(biāo)志一個(gè)字符串的結(jié)尾,順便記錄有多少個(gè)該字符串。
idx表示當(dāng)前要插入的節(jié)點(diǎn)(新建節(jié)點(diǎn))。

void insert(const string& s)
{
    int p = 0;// 從根開始找,如果沒有說明需要新的根
    for(int i = 0; i < s.size(); i++)
    {
        int u = s[i] - 'a';
        if(!son[p][u])// 沒有就創(chuàng)建
        {
            son[p][u] = ++idx;
        }
        p = son[p][u];
    }
    cnt[p]++;
}

用一張圖理解一下,假設(shè)現(xiàn)在要插入"ac"和"bc":
【數(shù)據(jù)結(jié)構(gòu)】深刨Trie樹(字典樹)
這也說明了不管是插入還是查找,第一個(gè)字符都是在第0層,所以初始化p = 0。

2.2 查找

查找的操作就類似于插入,如果不存在直接返回0即可。

int search(const string& s)
{
    int p = 0;
    for(int i = 0; i < s.size(); i++)
    {
        int u = s[i] - 'a';
        if(!son[p][u]) return 0;
        p = son[p][u];
    }
    return cnt[p];
}

2.3 例題:Trie字符串統(tǒng)計(jì)

題目鏈接

題目描述

維護(hù)一個(gè)字符串集合,支持兩種操作:

  1. I x 向集合中插入一個(gè)字符串 x;
  2. Q x 詢問一個(gè)字符串在集合中出現(xiàn)了多少次。
    共有 N個(gè)操作,所有輸入的字符串總長度不超過 1e5,字符串僅包含小寫英文字母。

輸入格式

第一行包含整數(shù) N,表示操作數(shù)。接下來 N行,每行包含一個(gè)操作指令,指令為 I x 或 Q x 中的一種。

輸出格式

對于每個(gè)詢問指令 Q x,都要輸出一個(gè)整數(shù)作為結(jié)果,表示 x在集合中出現(xiàn)的次數(shù)。
每個(gè)結(jié)果占一行。

數(shù)據(jù)范圍

1≤N≤2?1e4

輸入樣例:

5
I abc
Q abc
Q ab
I ab
Q ab

輸出樣例:

1
0
1

#include <iostream>
#include <string>

using namespace std;

const int N = 1e6 + 10;
int son[N][26];// 記錄下一個(gè)節(jié)點(diǎn)在第幾層
int cnt[N];// 標(biāo)識字符串結(jié)尾
int idx;// 記錄下一個(gè)要存節(jié)點(diǎn)的層數(shù)

void insert(const string& s)
{
    int p = 0;// 從根開始找,如果沒有說明需要新的根
    for(int i = 0; i < s.size(); i++)
    {
        int u = s[i] - 'a';
        if(!son[p][u])// 沒有就創(chuàng)建
        {
            son[p][u] = ++idx;
        }
        p = son[p][u];
    }
    cnt[p]++;
}

int search(const string& s)
{
    int p = 0;
    for(int i = 0; i < s.size(); i++)
    {
        int u = s[i] - 'a';
        if(!son[p][u]) return 0;
        p = son[p][u];
    }
    return cnt[p];
}


int main()
{
    int n;
    cin >> n;
    string s1, s2;
    while(n--)
    {
        cin >> s1 >> s2;
        if(s1 == "I")
        {
            insert(s2);
        }
        else
        {
            cout << search(s2) << endl;
        }
    }
    return 0;
}

三、應(yīng)用:最大異或?qū)?/h2>

題目鏈接

題目描述

在給定的 N個(gè)整數(shù) A1,A2……AN中選出兩個(gè)進(jìn)行 xor(異或)運(yùn)算,得到的結(jié)果最大是多少?

輸入格式

第一行輸入一個(gè)整數(shù) N。第二行輸入 N個(gè)整數(shù) A1~AN。

輸出格式

輸出一個(gè)整數(shù)表示答案。

數(shù)據(jù)范圍

1≤N≤105, 0≤Ai<231

輸入樣例:

3
1 2 3

輸出樣例:

3

思路分析:
首先我們要知道什么時(shí)候兩個(gè)數(shù)字異或值最大?
答案是當(dāng)兩個(gè)數(shù)的二進(jìn)制位每一位都不相同的時(shí)候最大。

我們知道一個(gè)數(shù)有32個(gè)比特位,最高位不用管(符號位),所以我們就要看第0 ~ 30位。
因?yàn)楸忍匚挥性有裕ㄖ挥袃蓱B(tài)),我們可以分兩種情況:一種是比特位相同,一種是不同,而為了保證最大,從最高位開始,如果兩種情況的話每次盡量往不同的方向走,只有一種情況就沒有辦法。我們邊查找邊統(tǒng)計(jì)總和,走到最后即可得到異或的值,所以我們邊查找就能邊統(tǒng)計(jì)最大的異或?qū)?/strong>。

#include <iostream>

using namespace std;

const int N = (1e5 + 10) * 31;

int son[N][2], idx;

void insert(int x)
{
    int p = 0;
    for(int i = 30; i >= 0; i--)
    {
        int u = (x >> i) & 1;
        if(!son[p][u]) son[p][u] = ++idx;
        p = son[p][u];
    }
}

int search(int x)
{
    int p = 0, res = 0;
    for(int i = 30; i >= 0; i--)
    {
        int u = (x >> i) & 1;
        // 盡量往不在的那一邊走
        // 另一邊存在就異或
        if(son[p][!u])
        {
            res = res * 2 + 1;
            p = son[p][!u];
        }
        else
        {
            res = res * 2;
            p = son[p][u];
        }
    }
    return res;
}

int main()
{
    int n;
    cin >> n;
    int res = 0;
    while(n--)
    {
        int x;
        cin >> x;
        insert(x);
        int tmp = search(x);
        res = max(res, tmp);
    }
    cout << res << endl;
    return 0;
}

四、總結(jié)

我們上面的題目也可以使用哈希來解決,但是trie樹在某些方面它的用途更大,比如說對于某一個(gè)單詞,我們要詢問它的前綴是否出現(xiàn)過。這樣hash就不好搞了,而用trie還是很簡單。
上面我們使用數(shù)組模擬出來的,當(dāng)然也可以用鏈?zhǔn)浇Y(jié)構(gòu):

#define MAX 26
typedef struct trie {
    struct trie* node[MAX];
    int v;
} Trie;

用一道leetcode的例題舉例:
題目鏈接
代碼:文章來源地址http://www.zghlxwxcb.cn/news/detail-412377.html

class Trie {
public:
    vector<Trie*> son;
    bool flag;

    Trie* searchend(string s)
    {
        Trie* node = this;
        for(int i = 0; i < s.size(); i++)
        {
            int u = s[i] - 'a';
            if(!node->son[u])
            {
                return nullptr;
            }
            node = node->son[u];
        }
        return node;
    }

    Trie() 
        : son(26)
        , flag(false)
    {}
    
    void insert(string word) {
        Trie* node = this;
        for(int i = 0; i < word.size(); i++)
        {
            int u = word[i] - 'a';
            if(!node->son[u])
            {
                node->son[u] = new Trie;
            }
            node = node->son[u];
        }
        node->flag = true;
    }
    
    bool search(string word) {
        Trie* node = searchend(word);
        if(node && node->flag)
        {
            return true;
        }
        return false;
    }
    
    bool startsWith(string prefix) {
        Trie* node = searchend(prefix);
        if(node)
        {
            return true;
        }
        return false;
    }
};

/**
 * Your Trie object will be instantiated and called as such:
 * Trie* obj = new Trie();
 * obj->insert(word);
 * bool param_2 = obj->search(word);
 * bool param_3 = obj->startsWith(prefix);
 */


到了這里,關(guān)于【數(shù)據(jù)結(jié)構(gòu)】深刨Trie樹(字典樹)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【高級數(shù)據(jù)結(jié)構(gòu)】Trie樹

    【高級數(shù)據(jù)結(jié)構(gòu)】Trie樹

    高效地存儲和查詢字符串的數(shù)據(jù)結(jié)構(gòu)。所以其重點(diǎn)在于:存儲、查詢兩個(gè)操作。 示例和圖片來自:https://blog.csdn.net/qq_42024195/article/details/88364485 假設(shè)有這么幾個(gè)字符串:b,abc,abd,bcd,abcd,efg,hii。最終存儲出來的Trie圖如下圖所示: 具體是怎么存的呢?對于每一個(gè)字符串,

    2024年03月10日
    瀏覽(22)
  • 【數(shù)據(jù)結(jié)構(gòu)基礎(chǔ)】樹 - 前綴樹(Trie Tree)

    【數(shù)據(jù)結(jié)構(gòu)基礎(chǔ)】樹 - 前綴樹(Trie Tree)

    Trie,又稱字典樹、單詞查找樹或鍵樹,是一種樹形結(jié)構(gòu),是一種哈希樹的變種。典型應(yīng)用是用于統(tǒng)計(jì),排序和保存大量的字符串(但不僅限于字符串),所以經(jīng)常被搜索引擎系統(tǒng)用于文本詞頻統(tǒng)計(jì)。它的優(yōu)點(diǎn)是:利用字符串的公共前綴來減少查詢時(shí)間,最大限度地減少無謂的

    2024年02月07日
    瀏覽(28)
  • LeetCode、208. 實(shí)現(xiàn) Trie (前綴樹)【中等,自定義數(shù)據(jù)結(jié)構(gòu)】

    LeetCode、208. 實(shí)現(xiàn) Trie (前綴樹)【中等,自定義數(shù)據(jù)結(jié)構(gòu)】

    博主介紹:?目前全網(wǎng)粉絲2W+,csdn博客專家、Java領(lǐng)域優(yōu)質(zhì)創(chuàng)作者,博客之星、阿里云平臺優(yōu)質(zhì)作者、專注于Java后端技術(shù)領(lǐng)域。 涵蓋技術(shù)內(nèi)容:Java后端、算法、分布式微服務(wù)、中間件、前端、運(yùn)維、ROS等。 博主所有博客文件目錄索引:博客目錄索引(持續(xù)更新) 視頻平臺:

    2024年02月19日
    瀏覽(21)
  • 【Redis】基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)-字典

    【Redis】基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)-字典

    基本語法 字典是Redis中的一種數(shù)據(jù)結(jié)構(gòu),底層使用哈希表實(shí)現(xiàn),一個(gè)哈希表中可以存儲多個(gè)鍵值對,它的語法如下,其中KEY為鍵,field和value為值(也是一個(gè)鍵值對): 根據(jù)Key和field獲取value: 哈希表 數(shù)據(jù)結(jié)構(gòu) dictht dictht是哈希表的數(shù)據(jù)結(jié)構(gòu)定義: table:哈希表數(shù)組,數(shù)組中的

    2024年02月07日
    瀏覽(21)
  • 字典樹的數(shù)據(jù)結(jié)構(gòu)

    字典樹的數(shù)據(jù)結(jié)構(gòu)

    Trie字典樹主要用于存儲字符串, Trie 的每個(gè) Node 保存一個(gè)字符。用鏈表來描述的話,就是一個(gè)字符串就是一個(gè)鏈表。每個(gè)Node都保存了它的所有子節(jié)點(diǎn)。 例如我們往字典樹中插入 see、pain、paint 三個(gè)單詞,Trie字典樹如下所示: 也就是說如果只考慮小寫的26個(gè)字母,那么Trie字典

    2024年02月12日
    瀏覽(22)
  • 數(shù)據(jù)結(jié)構(gòu)---字典樹(Tire)

    數(shù)據(jù)結(jié)構(gòu)---字典樹(Tire)

    字典樹是一種能夠快速插入和查詢字符串的多叉樹結(jié)構(gòu),節(jié)點(diǎn)的編號各不相同,根節(jié)點(diǎn)編號為0 Trie樹,即字典樹,又稱單詞查找樹或鍵樹,是一種樹形結(jié)構(gòu),是一種哈希樹的變種。 核心思想也是通過空間來換取時(shí)間上的效率 在一定情況下字典樹的效率要比哈希表要高 字典樹

    2024年02月21日
    瀏覽(19)
  • 一鍵導(dǎo)出數(shù)據(jù)庫中表結(jié)構(gòu)定義(數(shù)據(jù)字典)的工具

    導(dǎo)出數(shù)據(jù)庫中標(biāo)的定義,即所謂的數(shù)據(jù)字典 一、新建maven工程中加入依賴 在maven工程的pom.xml中添加依賴 二、在maven工程,將如下GenerateDocument .java文件加入工程中; 修改想要導(dǎo)出的mysql鏈接參數(shù),直接執(zhí)行即可導(dǎo)入數(shù)據(jù)庫設(shè)計(jì)的word文檔

    2024年02月06日
    瀏覽(24)
  • 【Python】基礎(chǔ)數(shù)據(jù)結(jié)構(gòu):列表——元組——字典——集合

    【Python】基礎(chǔ)數(shù)據(jù)結(jié)構(gòu):列表——元組——字典——集合

    Python提供了多種內(nèi)置的數(shù)據(jù)結(jié)構(gòu),包括列表( List )、元組( Tuple )和字典( Dictionary )。這些數(shù)據(jù)結(jié)構(gòu)在Python編程中都有著廣泛的應(yīng)用,但它們各有特點(diǎn)和適用場景。 列表是一種有序的集合,可以隨時(shí)添加和刪除其中的元素。列表是可變的,也就是說,你可以修改列表的

    2024年02月10日
    瀏覽(25)
  • Python-基礎(chǔ)篇-數(shù)據(jù)結(jié)構(gòu)-列表、元組、字典、集合

    Python-基礎(chǔ)篇-數(shù)據(jù)結(jié)構(gòu)-列表、元組、字典、集合

    列表、元組 字典、集合 ??正如在現(xiàn)實(shí)世界中一樣,直到我們擁有足夠多的東西,才迫切需要一個(gè)儲存東西的容器,這也是我堅(jiān)持把數(shù)據(jù)結(jié)構(gòu)放在最后面的原因一一直到你掌握足夠多的技能,可以創(chuàng)造更多的數(shù)據(jù),你才會重視數(shù)據(jù)結(jié)構(gòu)的作用。這些儲存大量數(shù)據(jù)的容器,在

    2024年01月21日
    瀏覽(26)
  • 211. 添加與搜索單詞 - 數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì)---------------字典樹

    211. 添加與搜索單詞 - 數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì)---------------字典樹

    211. 添加與搜索單詞 - 數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì) https://leetcode.cn/problems/design-add-and-search-words-data-structure/description/

    2024年02月14日
    瀏覽(18)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包