字典树模板

字典树称单词查找树, Trie树,是一种 树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。
它有3个基本性质:
1 根节点不包含字符,除根节点外每一个节点都只包含一个字符。
2 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。
3 每个节点的所有子节点包含的字符都不相同。

#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
const int M = 1e4 + 5;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
typedef long long ll;
int tree[N][26];     /// 26代表26个字母,根据题目需要也可以换成别的字符数量
int num[N];    /// 到该结点形成的字符串的前缀数量(包括本身)
int pos;   /// 初始值为1
void Insert(char* word)
{
    int u = 0;
    int len = strlen(word);
    for (int i = 0; i < len; i++){
        int v = word[i] - '0';
        if (tree[u][v] == 0){
            tree[u][v] = pos++;
        }
        u = tree[u][v];
        num[u]++;
    }
}
int Find(char* word)   //返回以某个字符串为前缀的单词的数量
{
    int u = 0;
    int len = strlen(word);
    for (int i = 0; i < len; i++){
        int v = word[i] - '0';
        if (tree[u][v] == 0) return 0;
        u = tree[u][v];
    }
    return num[u];
}

HDU 1671 题目链接

题意

给出n个字符串,如果一个字符串是另一个字符串的前缀就输出NO,否则输出YES

思路

字典树模板题(N的数量不能太大,会超内存)

#include <bits/stdc++.h>
using namespace std;
const int N = 3e5 + 5;
const int M = 1e4 + 5;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
typedef long long ll;
int tree[N][10];
int num[N];
char word[M][13];
int pos;   /// 初始值为1
void Insert(char* word)
{
    int u = 0;
    int len = strlen(word);
    for (int i = 0; i < len; i++){
        int v = word[i] - '0';
        if (tree[u][v] == 0){
            tree[u][v] = pos++;
        }
        u = tree[u][v];
        num[u]++;
    }
}
int Find(char* word)   //返回以某个字符串为前缀的单词的数量
{
    int u = 0;
    int len = strlen(word);
    for (int i = 0; i < len; i++){
        int v = word[i] - '0';
        if (tree[u][v] == 0) return 0;
        u = tree[u][v];
    }
    return num[u];
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--){
        int n;
        scanf("%d",&n);
        memset(tree,0,sizeof(tree));
        memset(num,0,sizeof(num));
        pos = 1;
        for (int i = 0; i < n; i++){
            scanf("%s",word[i]);
            Insert(word[i]);
        }
        bool flag = true;
        for (int i = 0; i < n; i++){
            if (Find(word[i]) > 1){
                flag = false;
                break;
            }
        }
        if (flag) cout << "YES" << endl;
        else cout << "NO" << endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值