【前缀个数】 前缀统计

传送门

题意

给定(N)个字符串,(S_{1}、S_{2}、dots S_{N})(M)个询问,每次询问给定一个字符串(T),求出在(S_{1}、S_{2}、dots S_{N})中有多少是(T)的子串

数据范围

字符串你的总长度(leq 10^{6})

题解

先将所有的字符串插入字典树之中,然后对每次给定的字符串(T),进行查询操作,累计以其中每个字符结尾的字符串个数即可、

  • 注意第一个节点也就是根是空节点

Code

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)

const int N=1e5+10;

int trie[N][26],cnt[N],tot=1;
char s[N];
void insert(char s[])
{
    int p=1;
    for(int i=0;s[i];i++)
    {
        int c=s[i]-'a';
        if(!trie[p][c]) trie[p][c]=++tot;
        p=trie[p][c];
    }
    cnt[p]++;
}
int query(char s[])
{
    int res=0,p=1;
    for(int i=0;s[i];i++)
    {
        int c=s[i]-'a';
        if(!trie[p][c]) return res;
        p=trie[p][c]; 
        res+=cnt[p];
    }
    return res;
}
void solve()
{
    int n,m;
    cin>>n>>m;
    while(n--)
    {
        cin>>s;
        insert(s);
    }
    while(m--)
    {
        cin>>s;
        cout<<query(s)<<endl;   
    }
}

int main()
{
    solve();
    return 0;
}
原文地址:https://www.cnblogs.com/hhyx/p/13386703.html