# 前缀统计~[字典树]

前缀统计~[字典树]

传送门

题意

给出N个字符串,进行M次询问,每次给出一个字符串,询问N个字符串中有多少个是它的前缀。

思路

字典树Trie入门题。

字典树最典型的应用就是用来存储字符串。

其中每个节点下有26个子节点(对应26个字母),根据新建节点的顺序使用idx为节点编号,根节点和空节点编号都为0,每个叶节点维护一个cnt,标记以这个叶节点结尾的字符串有几个。

使用这种存储方式可以很容易查找一个字符串是否存在,以及出现过几次等等。

Code:

#include <bits/stdc++.h>
using namespace std;
#define fre freopen("data.in","r",stdin);
#define ms(a) memset((a),0,sizeof(a))
#define go(i,a,b) for(register int (i)=(a);(i)<(b);++(i))
#define rep(i,a,b) for(register int (i)=(a);(i)<=(b);++(i))
#define sf(x) scanf("%d",&(x))
#define reg register
typedef long long LL;
const int inf=(0x3f3f3f3f);
const int maxn=1e6+5;
int son[maxn][30]; //维护字典树
int cnt[maxn],idx,n,m; //idx为使用到的节点编号
char str[maxn];
inline void insert(char *str){
    int p=0,u;//p表示当前的根节点
    for(int i=0;str[i];++i){
        u=str[i]-'a';
        if(!son[p][u])son[p][u]=++idx; //如果这个节点不存在,那么为这个节点编号,表示新建这个节点,节点从1开始编号
        p=son[p][u]; //沿着节点一直走到叶节点
    }
    ++cnt[p];//统计以该叶节点结尾的字符串的个数
}
inline LL query(char *str){
    int p=0,u;
    LL ans=0;
    for(int i=0;str[i];++i){
        u=str[i]-'a';
        if(!son[p][u])return ans;
        ans+=cnt[son[p][u]];//遍历字符串,统计前缀
        p=son[p][u];
    }
    return ans;
}
int main(){
    sf(n);sf(m);
    while(n--){
        scanf(" %s",str);
        insert(str);
    }
    while(m--){
        scanf(" %s",str);
        printf("%lld\n",query(str));
    }
    return 0;
}

原文地址:https://www.cnblogs.com/sstealer/p/12233104.html

时间: 2024-10-08 18:49:59

# 前缀统计~[字典树]的相关文章

AcWing 142. 前缀统计 字典树打卡

给定N个字符串S1,S2…SNS1,S2…SN,接下来进行M次询问,每次询问给定一个字符串T,求S1S1-SNSN中有多少个字符串是T的前缀. 输入字符串的总长度不超过106106,仅包含小写字母. 输入格式 第一行输入两个整数N,M. 接下来N行每行输入一个字符串SiSi. 接下来M行每行一个字符串T用以询问. 输出格式 对于每个询问,输出一个整数表示答案. 每个答案占一行. 输入样例: 3 2 ab bc abc abc efg 输出样例: 2 0 题意:让你计算前面有多少个字符串是查询的这

51nod round3# 序列分解(折半枚举+字典树)

小刀和大刀是双胞胎兄弟.今天他们玩一个有意思的游戏. 大刀给小刀准备了一个长度为n的整数序列.小刀试着把这个序列分解成两个长度为n/2的子序列. 这两个子序列必须满足以下两个条件: 1.他们不能相互重叠. 2.他们要完全一样. 如果小刀可以分解成功,大刀会给小刀一些糖果. 然而这个问题对于小刀来说太难了.他想请你来帮忙. Input 第一行给出一个T,表示T组数据.(1<=T<=5) 接下来每一组数据,输入共2行. 第一行包含一个整数n (2<=n<=40且为偶数). 第二行给出n

LightOJ 1269 - Consecutive Sum(字典树)

题目链接:LightOJ 1269 - Consecutive Sum 题目大意:给定一个序列,选定一段区间的亦或和,输出最大和最小. 解题思路:最大很简单,对所有前缀建立字典树,然后尽量往反向走:最小则需要往正向走,并且向正向走的时候要扣 除自己本身. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 50005 * 32; c

Barty&#39;s Computer 字典树

https://nanti.jisuanke.com/t/17122 Barty have a computer, it can do these two things. Add a new string to its memory, the length of this string is even. For given 44 strings a,b,c,da,b,c,d, find out how many strings that can be product by a+s1+b+c+s2

hdu 4760 Good Firewall(字典树)

题目链接:hdu 4760 Good Firewall 题目大意:有一个防火墙,具有添加一个子网络,删除一个子网络,以及转发包的操作. 添加操作包含子网络的id,以及子网络的子网掩码(计算出网络前缀,以及ip的下限),不会超过15个. 删除则是给定要删除的子网络id. 转发操作,给定两个ip,如果两个ip在同一个子网络中,则可以转发,否则丢弃. 解题思路:对子网掩码前缀建立字典树,每个前缀终止节点用一个set记录属于哪些子网络,ip下限.那么增加和删除操 作既可以解决了.对于查询操作,分别查询两

HDU 1251 统计难题 (字典树)(查询是否为前缀)

统计难题 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131070/65535 K (Java/Others)Total Submission(s): 37626    Accepted Submission(s): 13858 Problem Description Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的

HDU 1671 (字典树统计是否有前缀)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1671 Problem Description Given a list of phone numbers, determine if it is consistent in the sense that no number is the prefix of another. Let's say the phone catalogue listed these numbers: 1. Emergenc

【数据结构】字典树/Trie树/前缀树 - 字符串的统计、排序和保存

字典树 描述 字典树,又称单词查找树.Trie树.前缀树,是一种树形结构,是一种哈希树的变种. 典型应用是用于统计.排序和保存大量的字符串(但不仅限于字符串). 常见操作有插入和查找,删除操作少见. 性质 根节点不包含字符 除根节点外每一个节点都只包含一个字符 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串 每个节点的所有子节点包含的字符都不相同 优点 利用字符串的公共前缀来减少查询时间 最大限度地减少无谓的字符串比较 查询效率比哈希树高 自带字典序排序 直接判断重复,或者记

hdu 1251 统计难题(字典树)

Problem Description Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的前缀). Input 输入数据的第一部分是一张单词表,每行一个单词,单词的长度不超过10,它们代表的是老师交给Ignatius统计的单词,一个空行代表单词表的结束.第二部分是一连串的提问,每行一个提问,每个提问都是一个字符串. 注意:本题只有一组测试数据,处理到文件结束. Output 对于每个提