字典树的使用与应用

之前一直没怎么关心字符串的相关数据结构,最近心血来潮就想学一下,昨天看了下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;
}

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