码迷,mamicode.com
首页 > 其他好文 > 详细

# 前缀统计~[字典树]

时间:2020-01-25 16:47:27      阅读:84      评论:0      收藏:0      [点我收藏+]

标签:its   master   content   freopen   tps   出现   入门   alt   就是   

前缀统计~[字典树]

传送门

题意

给出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;
}

# 前缀统计~[字典树]

标签:its   master   content   freopen   tps   出现   入门   alt   就是   

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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!