Trie树简介 ( 洛谷P2580题解 )

看题解的请直接跳到模板

学Trie树的推荐 这篇文章

算法用途

又称单词查找树,字典树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。(无脑贴百科^_^)

算法思想

每次将一个字符串保存到树中,在查询时利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较。

感觉Trie相对而言还是比较好理解的,具体看模板注释,这里就不多讲了。

模板

洛谷P2580

#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN 500000
using namespace std;
int n,m,k;
int son[MAXN+5][26];//son[i][j]存的是第i号节点第j个字符的子节点。
char s[55];
bool ex[MAXN+5],f[MAXN+5];//ex判 断这个人名是否出现过,f判 断以这个节点为结尾的是否是人名
int calc(char c){
    return c-'a';
}
//插入
void nsrt(char s[]){
    int now=0;//当前节点的编号
    for (int i=0;s[i];i++){
        if (!son[now][calc(s[i])])//如果这个节点的儿子并没有出现过
            son[now][calc(s[i])]=++k;//加一个节点当他的儿子
        now=son[now][calc(s[i])];//继续循环
    }
    f[now]=true;//以这个节点为结尾字符串的是人名
}
//查询
int srch(char s[]){
    int now=0;
    for (int i=0;s[i];i++){
        if (!son[now][calc(s[i])])//如果这个人名根本没有出现过
            return 2;
        now=son[now][calc(s[i])];//继续循环
    }
    if (!ex[now]){//如果这个人还没被点到
        ex[now]=true;//打上标记
        return 0;
    }
    //如果这个人已经点到过了
    return 1;
}
int main(){
    scanf("%d",&n);
    k=0;
    memset(son,0,sizeof(son));
    memset(f,false,sizeof(f));
    memset(ex,false,sizeof(ex));
    for (int i=1;i<=n;i++){
        scanf("%s",s);
        nsrt(s);//插入
    }
    scanf("%d",&m);
    for (int i=1;i<=m;i++){
        scanf("%s",s);
        int flag=srch(s);//查询
        switch (flag){
            case 0:{
                printf("OK\n");
                break;
            }
            case 1:{
                printf("REPEAT\n");
                break;
            }
            default:{
                printf("WRONG\n");
                break;
            }
        }
    }
    return 0;
}
    原文作者:Trie树
    原文地址: https://blog.csdn.net/a1799342217/article/details/76572433
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注