主要是有个技巧
每个询问串s+'{'+s拼接起来
每个模板串p+'{'+s拼接起来
所有模板串建立AC自动机
询问串直接匹配,
同时还要满足询问串原长度+1>=模板串拼接后长度,否则会因前缀和后缀有重叠部分而不符合
1 // #include <bits/stdc++.h> 2 #include <iostream> 3 #include <cstdio> 4 #include <queue> 5 #include <cstring> 6 #include <cctype> 7 #include <set> 8 #include <cmath> 9 #include <algorithm> 10 #define For(i,a,b) for(int i=a;i<=b;++i) 11 #define Dec(i,b,a) for(int i=b;i>=a;--i) 12 #define file() freopen("c://users/asus/desktop/v.txt","r",stdin); 13 #define inf 0x3f3f3f3f 14 using namespace std; 15 16 typedef long long ll; 17 inline ll qr(){ 18 ll x=0,f=1; char ch; 19 while(!isdigit(ch=getchar())) if(ch=='-') f=-1; 20 while(isdigit(ch)){x=(x<<3)+(x<<1)+(ch^48); ch=getchar();} 21 return x*f; 22 } 23 const int N = 100010, M = 1000010; 24 string Q[N],s,p; 25 int c[N<<5][27],pos[N],f[N<<5],len[N<<5],ct; 26 int n,q,ans[N<<5],l[N]; 27 void clr(int x) 28 { 29 memset(c[x],0,sizeof c[x]); 30 f[x]=len[x]=0; 31 } 32 void init() 33 { 34 fill(ans,ans+1+ct,0); 35 fill(pos,pos+1+q,0); 36 clr(ct=0); 37 } 38 void ins(string s,int k) 39 { 40 int u=0; 41 for(int i=0;i<s.length();++i) 42 { 43 int v=s[i]-'a'; 44 if(!c[u][v]) c[u][v]=++ct,clr(ct),len[ct]=i+1; 45 u=c[u][v]; 46 } 47 pos[k]=u; 48 } 49 void getfail() 50 { 51 queue<int> q; 52 For(i,0,26) if(c[0][i]) q.push(c[0][i]); 53 while(!q.empty()) 54 { 55 int u=q.front(); q.pop(); 56 For(i,0,26) 57 { 58 int &v=c[u][i]; 59 if(v) f[v]=c[f[u]][i],q.push(v); 60 else v=c[f[u]][i]; 61 } 62 } 63 } 64 void qry(string s,int k) 65 { 66 int u=0; 67 for(int i=0;i<s.length();++i) 68 { 69 u=c[u][s[i]-'a']; 70 for(int t=u; t; t=f[t]) 71 if(len[t]<=k) ans[t]++; 72 } 73 } 74 int main() 75 { 76 // file(); 77 ios::sync_with_stdio(0); 78 int kase; cin >> kase; 79 while(kase--) 80 { 81 cin >> n >> q; 82 init(); 83 For(i,1,n) 84 { 85 cin >> Q[i]; 86 l[i]=Q[i].length()+1; 87 Q[i]=Q[i]+'{'+Q[i]; 88 } 89 For(i,1,q) 90 { 91 cin >> s >> p; 92 s = p+'{'+s; 93 ins(s,i); 94 } 95 getfail(); 96 For(i,1,n) qry(Q[i],l[i]); 97 For(i,1,q) cout<<ans[pos[i]]<<"\n"; 98 } 99 return 0; 100 }