# 접두어 통계 ~ [트라이]

통계 접두사 ~ [트라이]

문제의 의미

N의 문자열을 감안할 때, M 시간이 될 때마다 주어진 문자열, N은 접두사의 수 쿼리 문자열을 요청했다.

사고

트라이 트라이 항목의 제목입니다.

트라이의 가장 일반적인 응용 프로그램은 문자열을 저장하는 데 사용됩니다.

26 리프 노드 IDX 노드 ID에 새로운 노드 및 빈 루트 노드의 시퀀스를 사용하여 (26 글자에 대응하는) 노드의 각 자식 노드는, 0 번째의되고, 각각의 리프 노드는 CNT 마커를 유지 문자열의 몇 가지 끝이있다.

이 저장소로 문자열이있는 경우 쉽게 찾을 수 등 몇 번이 있었다.

암호:

#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;
}

추천

출처www.cnblogs.com/sstealer/p/12233104.html