Trie 字典树

参考文献 :《信息奥赛一本通》,《算法竞赛进阶指南》

根据一位大佬模仿下排版....

介绍:

字典树也叫做Trie或者字母树,指的是某个字符串集合,如{AAA,AAG,T.TCA,TG}这样的

集合对应的形的有根树,用图片解释食用更香:

每个顶点代表从根到该节点所对应的字符串,就是从根到这个节点的子符全部串在一起,

所以我们也叫Trie上的边叫做转移,顶点为状态。

顶点上还能存储额外信息,如下

这些从根到这些标红点组成的字符串都是集合中的元素,所以叫他们为单词节点(结==节,懒得改了)

还有,任意一个线节点代表的字符串,都是这些实际字符串中某些串的前缀。specially,根节点表示空串。

   任意一节点,到子节点边上字符都不同,这就是利用了串的公共前缀,如TG与TCA公共前缀为T....

     本质上它就是通过空间去换取时间。

操作


1.初始化:

一棵空的Trie只剩下一个根节点,它的字符指针指向空,显然。

2.插入操作

当我们需要插入一个字符串s时,我们让一个指针P先指向根节点,然后依次扫描s中的每个字符x:

  若P的x字符指针指向一个已经存在的节点A,则让P = A;

  若P的x字符指针指向空,就是原来不存在这个字符的连接节点,那就得给它构造一个节点,再让P的x字符指针指向A,最后让P=A;

  当s字符全部扫描完毕,就在当前节点P标记它是末尾。

long trie[MAXN][26],tot=1;//初始化,且假定字符串全    
bool end[MAXN];              //由小写字母构成
inline void insert(char* s){
    long len=strlen(s),p=1;
    for(long i=0;i<len;i++){
    long ch=s[i]-'a';
    if(trie[p][ch]==0) trie[p][ch]=++tot;
    p=trie[p][ch];
        }
    end[p]=1;
}  

  

3.查询操作

当我们需要查询时,我们就先让一个指针P指向根结点,再依次扫描s中每一个字符x:

  若P的x字符指针指向空,那就是没找到嘛,所以就干脆不找下去了,前缀都不一样找下去没啥意思。

  若P的x字符指针指向一个已经存在的节点A,那就是还能有,于是让P=A;

  当s扫描一遍后,若发现当前P被标记在一个字符串的末尾,则说明s是在这棵字典树是存在的,反之则说明s没在里面。

bool search(char* s){
    long len=strlen(s),p=1;
    for(long i=0;i<len;i++){
    p=trie[p][s[i]-'a'];
    if(p==0) return 0;//只要指向下一个为空,那就是没有了
    }
    reuturn end[p];//不能直接判1,因为可能这只是某个字
                          //符串的前缀而已    
}

  

~~~字符数据都体现在边上,节点只是保留额外信息,空间复杂度为O(NC),N为节点数,C为字符集大小。

其余的只能多刷刷题

kmp和trie只是为了给AC自动机打基础

原文地址:https://www.cnblogs.com/yuzhe123/p/13333207.html