题目链接:HDU - 6096
前后缀分开的,很麻烦,所以想办法拼凑在一起。
对每个字符串例如1234 ,我们构造成 1 4 2 3 3 2 4 1
然后对查询的串一样构造即可,当某个不存在时,用特殊符号代替。
然后防止前后串重叠,所以我们按照长度排序。离线做。如果强制在线的话,就只能换成可持久化Trie了
AC代码:
#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=1e6+10;
int n,q,t[N][26],idx,res[N],sz[N]; string str,s,tmp;
struct node{string s; int sz,f,id;}a[N<<1];
inline void insert(string &str){
int p=0;
for(int i=0;i<str.size();i++){
int k=str[i]-'a';
if(!t[p][k]) t[p][k]=++idx;
p=t[p][k]; sz[p]++;
}
}
int ask(int x,int p,string &str){
if(x==str.size()) return sz[p];
int res=0;
if(str[x]=='*'){
for(int i=0;i<26;i++) if(t[p][i]) res+=ask(x+1,t[p][i],str);
}else if(t[p][str[x]-'a']) res+=ask(x+1,t[p][str[x]-'a'],str);
return res;
}
void solve(){
cin>>n>>q; memset(t,0,sizeof t); idx=0; memset(sz,0,sizeof sz);
for(int i=1,l,r,f;i<=n;i++){
cin>>str; tmp=""; l=0,r=str.size()-1,f=1;
while(r>=0){
if(f) tmp+=str[l++];
else tmp+=str[r--];
f^=1;
}
a[i].s=tmp,a[i].sz=str.size(),a[i].f=0;
}
for(int i=1,l,r,f;i<=q;i++){
cin>>str>>s; tmp=""; l=0,r=s.size()-1,f=1;
while(l<str.size()||r>=0){
if(f) tmp+=(l==str.size()?'*':str[l++]);
else tmp+=(r>=0?s[r--]:'*');
f^=1;
}
a[i+n].s=tmp,a[i+n].sz=str.size()+s.size(),a[i+n].f=1,a[i+n].id=i;
}
sort(a+1,a+1+n+q,[](node a,node b){return a.sz==b.sz?a.f<b.f:a.sz>b.sz;});
for(int i=1;i<=n+q;i++){
if(!a[i].f) insert(a[i].s);
else res[a[i].id]=ask(0,0,a[i].s);
}
for(int i=1;i<=q;i++) cout<<res[i]<<'\n';
}
signed main(){
ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
int T; cin>>T; while(T--) solve();
return 0;
}