# 前缀统计~[字典树]

Posted sstealer

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了# 前缀统计~[字典树]相关的知识,希望对你有一定的参考价值。

前缀统计~[字典树]

传送门

题意

给出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
",query(str));
    }
    return 0;
}

以上是关于# 前缀统计~[字典树]的主要内容,如果未能解决你的问题,请参考以下文章

HDU-1251统计难题 ,字典树

字典树(前缀树)--Trie

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

Trie树(字典树)实现词频统计或前缀匹配类型的问题

Trie树(字典树)实现词频统计或前缀匹配类型的问题

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