Trie树

written by oneman233
2019-09-04

动态开点的祖宗,$AC$自动机的基础,字符串处理的利器,甚至能在上面$dp$。

比如插入单词$he$、$her$、$she$、$shit$之后:

Trie树形态

字典树可以在$O(n)$的时间内找到某个长为$n$的字符串是否在一堆单词中出现过。

可以在节点末尾打上标记,或者记录每个节点被累加了多少次,根据题意不同进行调整。

初始节点全部指向$root$,也就是$0$。

每个节点都要分配一个独一无二的编号,虽然会增大空间消耗。

节点数上限是字符串总长度。

实际上建立一个$trie$数组储存后续指向哪个节点即可,如果那个节点存在,说明那个节点储存着一个对应的字符。

代码如下:

int tr[maxn][26],tot=1;
bool ed[maxn];
void in(char *s) {
    int l=strlen(s);
    int p=1;
    for(int i=0;i<l;++i) {
        int pos=s[i]-'a';
        if(tr[p][pos]==0)
            tr[p][pos]=++tot;// 新建节点
        p=tr[p][pos];
        ed[p]=1;
    }
}
bool ask(char *s) {
    int l=strlen(s);
    int p=1;
    for(int i=0;i<l;++i) {
        int pos=s[i]-'a';
        p=tr[p][pos];
        if(p==0) return 0;// 节点不存在旧一定不在原单词中
    }
    return ed[p];// 没有终止标记也一定不在原单词中
}