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

    Trie树

    概要:

      字典树算法主要是对字符串进行处理,最后形成形如下图的trie树

      字典树主要用来查询前缀出现次数,字符串以前缀代表,查找单词,对某个单词的操作和询问

      在形成字典树的时候遵循的原则:

      1.根节点0不标记如图所示,单词是否出现以单词的下个节点来作为判断如果上所示的'$',实际上也就是每个字符都是存在边上的

      2.单词的插入,首先单词cat进行插入,然后下一个下一个,若单词的前缀相同的时候用的是同一个节点的分支

      3.一个节点最多就26个分支所以模板代码的数组开的[][26]

      trie树模板:

      进行单词的插入:

    void Insert(char s[],int rt)
    {
        for(int i=0;s[i]!='';++i)
        {
            int id=s[i]-'a';
            if(!trie[rt][id])//现在插入的之前未出现过
                trie[rt][id]=++tot;
            rt=trie[rt][id];
    //        ++sum[rt];
        }
    //    vis[rt]=1;
    }

      单词是否出现过-注意如果不是查询前缀还要做的一步就是查询这个节点结束的位置在vis中是不是一个单词的结束点

    int Find(char s[],int rt)
    {
        for(int i=0;s[i]!='';++i)
        {
            int id=s[i]-'a';
            if(trie[rt]id]==0) return 0;//无此节点
            rt=trie[rt][id];
        }
        return 1;
    }

       查询前缀出现的次数

    int SearchNumber(char s[],int rt)//寻找前缀数
    {
        for(int i=0;s[i]!='';++i)
        {
            int id=s[i]-'a';
            if(!trie[rt][id]) return 0;
            root=trie[rt][id];
        }
        return sum[rr];//找到前缀
    
    }

      查询能代表单词的前缀

    void ask(char s[],int rt)//用前缀来代表整个单词
    {
        for(int i=0;s[i]!='';++i)
        {
            if(sum[rt]==1) break;
            int id=s[i]-'a';
            printf("%c",s[i]);
            rt=trie[rt][id];
        }
    }
    const int maxn=1e6+10;
    int trie[maxn][27];
    int tot=1,n;
    //bool vis[maxn];//检查是否为单词
    int sum[maxn];

      

    注意:单词的前缀和单词的结束节点都是在trie[rt][id]存好后的下一个节点,具体看上面的图分析

     应用:

      查询能代表单词的前缀

      POJ2001-Shortest Prefixes

    #include <iostream>
    #include<algorithm>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <queue>
    #include<map>
    #include<set>
    #include<sstream>
    #define INF 0x3f3f3f3f
    #define DOF 0x7f7f7f7f
    #define mem(a,b) memset(a,b,sizeof(a))
    #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    typedef long long ll;
    using namespace std;
    const int maxn=1e6+10;
    int trie[maxn][27];
    int tot=1,n;
    //bool vis[maxn];//检查是否为单词
    char s[1010][35];
    int sum[maxn];
    void Insert(char s[],int rt)
    {
        for(int i=0;s[i]!='';++i)
        {
            int id=s[i]-'a';
            if(!trie[rt][id])//现在插入的之前未出现过
                trie[rt][id]=++tot;
            rt=trie[rt][id];
    //        ++sum[rt];
        }
    //    vis[rt]=1;
    }
    
    int Find(char s[],int rt)
    {
        for(int i=0;s[i]!='';++i)
        {
            int id=s[i]-'a';
            if(trie[rt]id]==0) return 0;//无此节点
            rt=trie[rt][id];
        }
        return 1;
    }
    
    int SearchNumber(char s[],int rt)//寻找前缀数
    {
        for(int i=0;s[i]!='';++i)
        {
            int id=s[i]-'a';
            if(!trie[rt][id]) return 0;
            root=trie[rt][id];
        }
        return sum[rr];//找到前缀
    
    }
    
    void ask(char s[],int rt)//用前缀来代表整个单词
    {
        for(int i=0;s[i]!='';++i)
        {
            if(sum[rt]==1) break;
            int id=s[i]-'a';
            printf("%c",s[i]);
            rt=trie[rt][id];
        }
    }
    int main()
    {
    //    freopen("input.txt","r",stdin);
    //    freopen("output.txt","w",stdout);
        int n=0;
        while(scanf("%s",s[++n])!=EOF)
            Insert(s[n],0);
        for(int i=1;i<=n;++i)
        {
            printf("%s ",s[i]);
            ask(s[i],0);
            printf("
    ");
        }
    //    system("pause");
    
    }

    附上学习时候看的博客:https://www.cnblogs.com/TheRoadToTheGold/p/6290732.html

  • 相关阅读:
    凸透镜和凹透镜为什么分别对光有会聚作用和发散作用
    平面镜成像
    行政 申论 大纲
    专业科 大纲
    linux command --- terminal common commands
    3D VR卡镜的使用方法
    Structure From Motion(二维运动图像中的三维重建)
    双目摄像机
    对比手机SLAM和机器人SLAM
    3D indoor map positioning with a smartphone image
  • 原文地址:https://www.cnblogs.com/waryan/p/12620976.html
Copyright © 2011-2022 走看看