欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【模版】trie树

程序员文章站 2022-05-19 18:55:23
...

trie树


字符串树,多叉树。
每个结点保存的是单个字符,结点按从小到大的顺序编号。
对有公共前缀的若干组字符串,公共部分不用建立多余结点。
有插入和查询两种操作。代码很好记也很好理解。


算法流程:
整型二维数组 trie[][]trie[最大字符数量][字符种类数量] 。赋值 为 结点数。

插入:
对于要插入的字符串 SS。从前往后处理:判断当前字符有没有被记录过,如果没有被记录,则增加结点并记录(如果被记录过,即与之前插入的字符串有公共前缀,则不用增加结点)。然后跳到下一个结点处理下一个字符。
字符串 SS 的最后一个字符对应结点编号一定要标记,表示当前字符串结束。

void Insert()
{
    char key[1100];
    scanf("%s",key);
    int len = strlen(key), k = 0;
    for(int i = 0; i < len; i++)
    {
        int c = key[i] - 'a';
        if(!trie[k][c]) trie[k][c] = ++t;
        k = trie[k][c];
    }
    flg[k] = 1;
}

查询:
同插入一样,对字符串 SS 从前往后处理,判断当前位置的字符有没有提前被编号,如果没有则说明字符串 SS 尚未被插入。如果有被编号,则挪动至下一个结点继续查找下一个字符。
查询到最后一个字符时,需要判断当前的结点是否是 之前插入的字符串的结尾字符。(防止出现 当前查询的字符串 是 之前插入字符串的前缀的情况)

下列代码为例题的代码。

int Query()
{
    char key[1100];
    scanf("%s",key);
    int len = strlen(key), k = 0;
    for(int i = 0; i < len; i++)
    {
        int c = key[i] - 'a';
        if(!trie[k][c]) return 0;
        k = trie[k][c];
    }
    if(flg[k] == 0) return 0;
    cnt[k]++;
    return cnt[k];
}

例题:于是他错误的点名开始了
其他trie树题目:
[USACO08DEC]Secret Message G
[TJOI2010]阅读理解

相关标签: 算法【模版】