Trie树简介 ( 洛谷P2580题解 )

来源:互联网 发布:女生不发自拍 知乎 编辑:程序博客网 时间:2024/06/02 00:39

看题解的请直接跳到模板

学Trie树的推荐 这篇文章

算法用途

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

算法思想

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

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

模板

洛谷P2580

#include<cstdio>#include<cstring>#include<algorithm>#define MAXN 500000using 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;}