先建出trie树,暴力在trie树上dfs,三种情况分别对应字符串跳一下,trie树上跳一次,trie树上往不同方向跳一次,注意记录一下每个节点是否出现过,因为可能有同一个字符串经过不同的操作多次到达的情况。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#define maxn 200010
using namespace std;
int ch[maxn][26];
bool tag[maxn];
char s[maxn];
int q[maxn];
bool vis[maxn];
int ans,n,m,tot,len,top;
bool w;
void insert()
{
int len=strlen(s),x=0;
for (int i=0;i<len;i++)
{
if (ch[x][s[i]-'a']==-1) ch[x][s[i]-'a']=++tot;
x=ch[x][s[i]-'a'];
}
tag[x]=1;
}
void dfs(int x,int y,int f)
{
if (x==len && tag[y] && !f) {w=1;return;}
if (x==len && tag[y] && f) {if (!vis[y]) ans++,q[++top]=y,vis[y]=1;return;}
if (x<len && !f) dfs(x+1,y,1);
if (!f)
{
for (int i=0;i<26;i++)
if (ch[y][i]!=-1) {dfs(x,ch[y][i],1);if (i!=s[x+1]-'a') dfs(x+1,ch[y][i],1);}
}
if (x==len) return;
if (ch[y][s[x+1]-'a']!=-1) dfs(x+1,ch[y][s[x+1]-'a'],f);
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=0;i<=200000;i++)
for (int j=0;j<26;j++)
ch[i][j]=-1;
for (int i=1;i<=n;i++)
{
scanf("%s",s);
insert();
}
for (int i=1;i<=m;i++)
{
ans=0;w=0;
while (top) vis[q[top--]]=0;
scanf("%s",s+1);
len=strlen(s+1);
dfs(0,0,0);
if (w) printf("-1\n"); else printf("%d\n",ans);
}
return 0;
}