对trie建SAM,询问串倒过来跑到的节点的|right|即为答案。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 1000000010
#define N 2000010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
int n,m,trie[N][26],son[N][26],fail[N],len[N],size[N],tmp[N],id[N],q[N],cnt=1;
char s[N];
int ins(int c,int p)
{
int x=++cnt;len[x]=len[p]+1;size[x]=1;
while (!son[p][c]&&p) son[p][c]=x,p=fail[p];
if (!p) fail[x]=1;
else
{
int q=son[p][c];
if (len[p]+1==len[q]) fail[x]=q;
else
{
int y=++cnt;
len[y]=len[p]+1;
memcpy(son[y],son[q],sizeof(son[q]));
fail[y]=fail[q],fail[x]=fail[q]=y;
while (son[p][c]==q) son[p][c]=y,p=fail[p];
}
}
return x;
}
int run(char *s)
{
int n=strlen(s+1);
int k=1;for (int i=n;i>=1;i--) k=son[k][s[i]-'A'];
return k;
}
signed main()
{
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
n=read(),m=read();
for (int i=1;i<=n;i++)
{
char c=getc();int x=read();
trie[x][c-'A']=i;
}
int head=0,tail=1;q[1]=0;id[0]=1;
do
{
int x=q[++head];
for (int i=0;i<26;i++)
if (trie[x][i])
{
q[++tail]=trie[x][i];
id[q[tail]]=ins(i,id[x]);
}
}while (head<tail);
for (int i=1;i<=cnt;i++) tmp[len[i]]++;
for (int i=1;i<=cnt;i++) tmp[i]+=tmp[i-1];
for (int i=1;i<=cnt;i++) q[tmp[len[i]]--]=i;
for (int i=cnt;i>=2;i--) size[fail[q[i]]]+=size[q[i]];
while (m--)
{
scanf("%s",s+1);
printf("%d
",size[run(s)]);
}
return 0;
//NOTICE LONG LONG!!!!!
}