讲解在注释里
const int N=1e6+10;
char str[N];
int tree[N][26+5];//N个字符串,每个节点可能有26个字母作为子节点
int idx,n,m;
int cnt[N];
inline void insert(char s[]){
int p=0;//p是空节点
for(int i=0;s[i];++i){//脱离strlen的苦海,因为字符串的末尾是'\0'
int now=s[i]-'a';
int &son=tree[p][now];
if(!son)
son=++idx;
p=son;
}
cnt[p]++;//为了防止有重复字串,这里不能只记录bool 型变量表示end标记
}
inline int query(char s[]){
int res=0,p=0;
for(int i=0;s[i];++i){
int now=s[i]-'a';
int &son=tree[p][now];
if(son==0)return res;//一旦找到非前缀立即返回
res+=cnt[son];
p=son;
}
return res;
}
int main(){
rd(n),rd(m);
rep(i,1,n){
scanf("%s",str);
insert(str);
}
rep(i,1,m){
scanf("%s",str);
printf("%d\n",query(str));
}
return 0;
}