字典樹的使用與應用

之前一直沒怎麼關心字符串的相關數據結構,最近心血來潮就想學一下,昨天看了下manacher,感覺只是一個思想而已,並不是很難,然後又想起以前只是聽過的字典樹,大概知道是個什麼意思,一直沒來親手實現過,趁着中午沒課就自己敲了一下,發現實現也不難,大概寫了15min吧,就是感覺自己的代碼有點難看2333,試寫了一下hihocoder的hiho一下的題過了,還是挺高興吧。

字典樹應用的話最基本最普遍的也就是字典中查單詞了吧,思想的話就是利用字符串的公共前綴來降低查詢時間來提高效率,以給出的字典中的單詞來建樹,如下面這個例子,abcd和abd共用前綴ab,那麼就像下面這樣畫樹。

(圖網上找的)

下面附上我寫的辣雞代碼(這麼寫着方便,但肯定不快,就當留着做個紀念2333

http://hihocoder.com/problemset/problem/1014  這個的ac代碼)

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define EPS 1e-7
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
using namespace std;
typedef long long LL;
typedef pair<LL, LL> P;
const int maxn = 1e5 + 5;
const int mod = 1e8 + 7;

int n,m;
int L[maxn<<2];
struct edge{
    int to;
    char weight;
};
vector<edge>tree[maxn<<2];
int tmp;
void init(){
    tmp=1;
    memset(L,0,sizeof(L));
    for (int i=0;i<maxn;i++) tree[i].clear();
}
void add(char *s){
    int i=1,j=0,k;
    while (j!=strlen(s)){
        bool flag=0;
        for (k=0;k<tree[i].size();k++){
            if (tree[i][k].weight==s[j]) {
                flag=1;
                break;
            }
        }
        if (flag){
            i=tree[i][k].to;
            j++;
            L[i]++;
        }
        else {
            tree[i].push_back({++tmp,s[j]});
            L[tmp]++;
            i=tmp;
            j++;
        }
    }
}
int query(char *s){
    int i=1,j=0,k;
    while (j!=strlen(s)){
        bool flag=0;
        for (k=0;k<tree[i].size();k++){
            if (tree[i][k].weight==s[j]) {
                flag=1;
                break;
            }
        }
        if (flag){
            i=tree[i][k].to;
            j++;
        }
        else return 0;
    }
    return L[i];
}
char s[15];
int main (){
    scanf ("%d",&n);
    init();
    for (int i=0;i<n;i++){
        scanf ("%s",s);
        add(s);
    }
    scanf ("%d",&m);
    for (int i=0;i<m;i++){
        scanf ("%s",s);
        int ans=query(s);
        printf ("%d\n",ans);
    }
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章