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

原文地址:https://www.cnblogs.com/SeanOcean/p/11230605.html