• Trie树模板 + 例题


    字典树模板

    const int maxn=2e6+5;
    int tree[maxn][55];   //tree[i][j]表示节点i的第j个儿子的节点编号
    bool flagg[maxn];    //表示以该节点结尾的是一个单词
    int tot;    //总结点数
    void insert_(char *str)
    {
        int len=strlen(str);
        int root=0;
        for(int i=0;i<len;i++){
            int id=str[i]-'a';
            if(!tree[root][id])tree[root][id]=++tot;
            root=tree[root][id];
        }
        flagg[root]=true;
    }
    bool find_(char *str)
    {
        int len=strlen(str);
        int root=0;
        for(int i=0;i<len;i++)
        {
            int id=str[i]-'a';
            if(!tree[root][id])return false;
            root=tree[root][id];
        }
        return true;
    }
    void init()
    {
        for(int i=0;i<=tot;i++)
        {
            flagg[i]=false;
            for(int j=0;j<10;j++)
                tree[i][j]=0;
        }
        tot=0;
    }

    例题·

    1、HUD2072

          题意:统计一篇文章里不同单词出现次数。

          思路:字典树储存,进行多次查找和插入。用flagg判断是否为单词。

          代码:

    #include <iostream>
    #include <cstdio>
    #include <fstream>
    #include <algorithm>
    #include <cmath>
    #include <deque>
    #include <vector>
    #include <queue>
    #include <string>
    #include <cstring>
    #include <map>
    #include <stack>
    #include <set>
    #define ll long long
    #define MOD 998244353 
    #define INF 0x3f3f3f3f
    #define mem(a,x) memset(a,x,sizeof(a))  
    #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    using namespace std;
    const int maxn=2e6+5;
    int tree[maxn][30];   //tree[i][j]表示节点i的第j个儿子的节点编号
    bool flagg[maxn];    //表示以该节点结尾的是一个单词
    int sum[maxn]={0};
    int tot;    //总结点数
    void insert_(char *str,int len)
    {
        int root=0;
        for(int i=0;i<len;i++){
            int id=str[i]-'a';
            if(!tree[root][id])tree[root][id]=++tot;
            root=tree[root][id];
        }
        flagg[root]=true;
    }
    bool find_(char *str,int len)
    {
        int root=0;
        string ans="";
        for(int i=0;i<len;i++)
        {
            int id=str[i]-'a';
            ans+=str[i];
            if(!tree[root][id])return false;
            root=tree[root][id];
        }
        if(flagg[root]==true){
            return true;
        }else{
            return false;
        }
        
    }
    void init()
    {
        for(int i=0;i<=tot;i++)
        {
            flagg[i]=false;
            for(int j=0;j<10;j++)
                tree[i][j]=0;
        }
        tot=0;
    }
    string s;
    char s1[105];
    int main()
    {
        while(getline(cin,s))
        {
            int ans=0,k=0,d=0;
            if(s[0]=='#')break;
            for(int i=0;i<s.size();i++){
               if(s[i]==' '&&k==1){
                  if(!find_(s1,d)){
                     ans++;
                     insert_(s1,d);
                  }
                  k=0;
                  d=0;
               }else{
                  if(s[i]==' ')continue;
                  s1[d++]=s[i];
                  k=1;
               }
            }
            if(d!=0){
                if(!find_(s1,d)){
                     ans++;
                     insert_(s1,d);
                  }
            }
            cout<<ans<<endl;
            init();
        }
        return 0;
    }

          2、POJ2001

          题意:给你很多单词,问你每个单词的唯一的最短前缀。

          思路:我们先构建好Trie树,然后对每个单词进行find,递归到直到节点出现次数为1,表示这个节点只有这一个单词走过,返

                     回就ok。

          代码:

    #include <iostream>
    #include <cstdio>
    #include <fstream>
    #include <algorithm>
    #include <cmath>
    #include <deque>
    #include <vector>
    #include <queue>
    #include <string>
    #include <cstring>
    #include <map>
    #include <stack>
    #include <set>
    #define ll long long
    #define MOD 998244353 
    #define INF 0x3f3f3f3f
    #define mem(a,x) memset(a,x,sizeof(a))  
    #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    using namespace std;
    const int maxn=2e6+5;
    int tree[maxn][30];   //tree[i][j]表示节点i的第j个儿子的节点编号
    bool flagg[maxn];    //表示以该节点结尾的是一个单词
    int sum[maxn]={0};
    int tot;    //总结点数
    void insert_(char *str)
    {
        int len=strlen(str);
        int root=0;
        for(int i=0;i<len;i++){
            int id=str[i]-'a';
            if(!tree[root][id])tree[root][id]=++tot;
            sum[tree[root][id]]++;
            root=tree[root][id];
        }
        flagg[root]=true;
    }
    string find_(char *str)
    {
        int len=strlen(str);
        int root=0;
        string ans="";
        for(int i=0;i<len;i++)
        {
            int id=str[i]-'a';
            ans+=str[i];
            if(sum[tree[root][id]]<=1)return ans;
            root=tree[root][id];
        }
        return ans;
    }
    void init()
    {
        for(int i=0;i<=tot;i++)
        {
            flagg[i]=false;
            for(int j=0;j<10;j++)
                tree[i][j]=0;
        }
        tot=0;
    }
    char s[1005][25];
    int main()
    {
        int num=0;
        while(~scanf("%s",s[num])){
            insert_(s[num]);
            num++;
        }
        for(int i=0;i<num;i++)
        {
            printf("%s %s
    ",s[i],find_(s[i]).c_str());
        }
        return 0;
    }

       

    越自律,越自由
  • 相关阅读:
    C#通过反射获取类中的方法和参数个数,反射调用方法带参数
    C#利用WinRAR实现压缩和解压缩
    C# 使用HttpWebRequest Post提交数据,携带Cookie和相关参数示例
    C#使用Linq To XML读取XML,Linq生成XML,Linq创建带属性或带节点XML
    MVC使用Newtonsoft无需实体类,实现JSON数据返回给前端页面使用
    JSON对象与字符串之间的相互转换
    Javascript正则表达式详细讲解和示例,通俗易懂
    C#比较两个list集合,两集合同时存在或A集合存在B集合中无
    Uploadify 3.2上传文件,限制类型,大小,传递参数等
    c# 反射得到实体类的字段名称和值,DataTable转List<T>
  • 原文地址:https://www.cnblogs.com/ha-chuochuo/p/13435565.html
Copyright © 2020-2023  润新知