zoukankan      html  css  js  c++  java
  • Trie字典树

     

    一、简介

      将一个字符串用有根树的形式储存起来,树边对应着字符,树的节点储存着相关信息,边为转移,点为状态(官方简介

    二、基本性质

    •   根节点不包含字符,除根节点外每一个节点都只包含一个字符;
    •   从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串;
    •   每个节点的所有子节点包含的字符都不相同。

    三、操作实现

      1.初始化:

        仅含有一个根节点,该点的字符指针均指向空

      2.插入:

        当需要插入一个字符串S时,我们令一个指针起初指向根节点,然后扫描S中的字符

          (1).若指针P的c字符指针指向一个已经存在的节点Q,则令P=Q

          (2).若指针P的c字符指针指向空,则新建一个节点Q,则P的c字符指针指向Q,然后令P=Q

          (3).当S中的字符串扫描完毕时,在当前节点指针P上标记它是一个字符串的结尾

            

      3.查询:

        当需查询一个字符串S在Trie中是否存在时,我们令一个指针P起初指向根节点,然后依次扫描S中的每一个字符c

          (1).若指针P的c字符指针指向空,则说明S没有插入过Trie,查询结束

          (2).若指针P的c字符指向一个已经存在的节点Q,则令P=Q

          (3).当指针S中的字符扫描完毕,若当前节点P被标记为一个字符串的末尾,则说明Trie中已经存在,否则说明S中没有插入过Trie

     四:具体代码(POJ3630

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #define FORa(i,s,e) for(int i=s;i<=e;i++)
    #define FORs(i,s,e) for(int i=s;i>=e;i--)
    #define gc pa==pb&&(pb=(pa=buf)+fread(buf,1,100000,stdin),pa==pb)?EOF:*pa++
    #define File(name) freopen(name".in","r",stdin);freopen(name".out","w",stdout);
    
    using namespace std;
    static char buf[100000],*pa=buf,*pb=buf;
    inline int read();
    
    const int N=100,LEN=10;
    int T,n,tot,ch[N+1][LEN+1]; 
    char s[LEN+1];
    bool ans,end_p[N+1];
    void Clear()
    {
        memset(ch,0,sizeof(ch));
        memset(end_p,0,sizeof(end_p));
    }
    bool Insert(char *fs)
    {
        int len=strlen(fs),u=1;//从根节点开始search 
        bool flag=0;
        FORa(i,0,len-1)
        {
            int p=fs[i]-'0';
            if(!ch[u][p]) ch[u][p]=++tot;//遍历儿子中是否有搜索串中此时的字符,没有的话,在树上新建一个节点储存下来 
            else if(i==len-1) flag=1;//如果字符串在Trie数中能够找到,返回存在 
            u=ch[u][p];//迭代 
            if(end_p[u]) flag=1;//看此时从根节点到现在节点是否存在完整单词,有的话,就完成了前缀的任务,将旗帜转为1 
        }
        end_p[u]=1;//标记从根节点到此节点产生了一个单词 
        return flag;//返回答案 
    }
    int main()
    {
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d",&n);
            ans=0,tot=1;//初始化答案,更新根节点 
            Clear();//清楚字典树除根节点的一切信息 
            FORa(i,1,n)
            {
                scanf("%s",s);    
                if(Insert(s)) //插入字符串 
                {
                    ans=1;//判断Trie是否有S这个字符串 
                    break;    
                }
            } 
            ans?printf("NO"):printf("YES");
        }
        return 0;
    }
    inline int read()
    {
        register int x(0);register int f(1);register c(gc);
        while(c<'0'||c>'9') f=c=='-'?-1:1,c=gc;
        while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=gc;
        return  x*f;
    }

     五、相关文章链接

       https://pks-loving.blog.luogu.org/zi-fu-chuan-xue-xi-bi-ji-ha-xi-hash-yu-zi-dian-shu-trie

       https://blog.csdn.net/jiutianhe/article/details/8076835

  • 相关阅读:
    Xpath语法与lxml库的用法
    Selenium--使用参考
    PhantomJS的替代品--无头浏览器(Headless Chrome)
    为什么只有一个元素的tuple要加逗号?
    反爬利器--设置代理服务器
    LeetCode 221. 最大正方形 | Python
    LeetCode 572. 另一个树的子树 | Python
    LeetCode 98. 验证二叉搜索树 | Python
    LeetCode 45. 跳跃游戏 II | Python
    LeetCode 25. K 个一组翻转链表 | Python
  • 原文地址:https://www.cnblogs.com/SeanOcean/p/11230605.html
Copyright © 2011-2022 走看看