CH 1601 前缀统计 字典树模板题目

描述
给定N个字符串S1,S2...SN,接下来进行M次询问,每次询问给定一个字符串T,求S1~SN中有多少个字符串是T的前缀。输入字符串的总长度不超过10^6,仅包含小写字母。

输入格式
第一行两个整数N,M。接下来N行每行一个字符串Si。接下来M行每行一个字符串表示询问。

输出格式
对于每个询问,输出一个整数表示答案

样例输入
3 2
ab
bc
abc
abc
efg
样例输出
2
0

思路:字典树模板

初始化:一棵空Trie仅包含一个根节点,该点的字符指针均指向空

插入: 当需要插入一个字符串S时,我们令一个指针P起初指向根节点,然后依次扫描S中的每一个字符c

    1 .若P的c字符指针指向一个已经存在的节点Q,则令P=Q

    2.若P的c字符指针指向空,则新建一个节点Q,令P的c字符指针指向Q,然后令P=Q

   当S中的字符扫描完毕时,在当前节点P上标记它是一个字符串的末尾

检索:当需要检索一个字符串S在Trie上是否存在的时候,我们令一个指针P起初指向根节点,然后依次扫描S中的每一个字符

   1.若P的c字符指针指向空,则说明S没有被插入过Trie,结束检索

   2.若P的c字符指针指向一个已经存在的节点Q.则令P=Q

当S中的字符扫描完毕时,若当前节点P被标记为一个字符串的末尾。则说明S在Trie中存在,否则说明没有插入过Trie

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

using namespace std;

typedef long long ll;
const ll INF=1e12;
const int MAXN=1e6+5;
int trie[MAXN][27];
int cnt[MAXN],tot=1;
void iinsert(char *str)
{
    int len=strlen(str),p=0;
    for(int i=0;i<len;i++){
        int ch=str[i]-'a';
        if(!trie[p][ch])
            trie[p][ch]=++tot;
        p=trie[p][ch];
    }
    cnt[p]++;
}
int isearch(char *str)
{
    int ans=0;
    int len=strlen(str),p=0;
    for(int i=0;i<len;i++)
    {
        int ch=str[i]-'a';
        p=trie[p][ch];
        if(!p)
            return ans;
         ans+=cnt[p];
    }
    return ans;
}
int main()
{
    char s[MAXN];
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%s",s);
        iinsert(s);
    }
    for(int i=1;i<=m;i++){
        scanf("%s",s);
        printf("%d\n",isearch(s));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/deepseazbw/article/details/81304076
今日推荐