Trie樹,字典樹

TLSnail發表於2024-08-17

題目連結

字典樹的介紹

字典樹也叫(Trie樹),字典樹有插入和查詢兩個操作,我們先假設我們已經插入了單詞 befakebeefface 這幾個單詞,那麼我們可以建樹。

image

當我們查詢 befafAKefac 時,答案分別為:\(2,2,0,1\)

字典樹的插入

我們可以給樹上的每個節點標號,比如上面的樹,可標為:

image

根節點永遠都是 \(0\),而其他節點,按訪問順序來標號。

我們定義 son[i][w] 表示現在的編號 i 的下一個字元是 w 的編號是多少,比如,編號 i 所對應的字串是 t[i] 那麼 t[son[i][w]]=t[i]+w

設一個變數 p,表示現在訪問到的節點編號是多少,一開始的時候 p=0,然後如果 son[p][w]=0 那麼就新建一個節點編號,即 son[p][w]=++idx。接著 \(p\) 賦值成下一個節點的編號即 son[p][w],然後對應字串出現次數 cnt[p] 加一。

程式碼:

int idx=0;
void insert(char *s){
    int p=0;
    for(int i=0,w;w=s[i];i++){
        if(!son[p][w])son[p][w]=++idx;
        p=son[p][w];
        cnt[p]++;
    }
}

字典樹的查詢

首先還是設一個變數 p 表示現在訪問到的節點編號是多少,p 一開始在根節點,然後如果 son[p][w]=0 那麼就表示沒有這種字串,即返回 \(0\),否則的話,我們繼續訪問,最後我們列舉完整個字串,即查詢到 s 字串對應的編號 p,返回 cnt[p] 即可。

int query(char *s){
    int p=0;
    for(int i=0,w;w=s[i];i++){
        if(!son[p][w])return 0;
        p=son[p][w];
    }
    return cnt[p];
}

模板程式碼

題目連結

就是普通的模板,卡常卡過就行了。

#include<bits/stdc++.h>
#define fast ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);
#define rep(l,r,i) for(int i=l,END##i=r;i<=END##i;i++)
#define per(r,l,i) for(int i=r,END##i=l;i>=END##i;i--)
#define endl '\n'
#define pb push_back
#define mk make_pair
#define pii pair<int,int>
#define vi vector<int>
using ll=long long;
using ull=unsigned long long;
using namespace std;
const int INF=0x3f3f3f3f;
const int MAXN=3e6+10,MAXM=1e5+10;
int T,n,q,cnt[MAXN],idx;
char s[MAXM];
map<char,int>son[MAXN];
void insert(char *s){
    int p=0;
    for(int i=0,w;w=s[i];i++){
        if(!son[p][w]){
            son[p][w]=++idx;
            cnt[idx]=0;
        }
        p=son[p][w];
        cnt[p]++;
    }
}
int query(char *s){
    int p=0;
    for(int i=0,w;w=s[i];i++){
        if(!son[p][w])return 0;
        p=son[p][w];
    }
    return cnt[p];
}
void solve(){
    rep(0,idx,i)son[i].clear();
    idx=0;
    scanf("%d%d",&n,&q);
    rep(1,n,i){
        scanf("%s",s);
        insert(s);
    }
    while(q--){
        scanf("%s",s);
        printf("%d\n",query(s));
    }
}
int main(){
    cin>>T;
    while(T--)
        solve();
    return 0;
}

相關文章