题解
先说个题外话,这道题哈希用
upd:原因是写代码的时候没发现字符串访问了未赋值的地方导致哈希出了问题……有点内个了 o(╥﹏╥)o,哈希用
题意
已知
题目分析
首先一看内存限制,好家伙,32 MB,字典树建不下,这可怎么办?但我们可以发现,我们可以将询问离线下来,分开求
求
时间复杂度是优秀的
Code
#include <bits/stdc++.h>
#define uLL unsigned long long
using namespace std;
const int N = 3e4+5;
const uLL base = 31;
int n, q, ans[N];
uLL az[N], bb[N];
unordered_map <uLL, int> vis;
char s[N][35], t[N][35];
vector <int> to[N];
template <typename T> void read(T& x) {
x = 0; int f = 0; char c = getchar();
while(c < '0' || c > '9') f |= (c == '-'), c=getchar();
while(c >= '0' && c <= '9') x=(x<<1)+(x<<3)+(c^48), c=getchar();
x=(f ? -x : x);
}
int lne; char put[105];
template <typename T> void write(T x, char ch) {
lne = 0; if(x < 0) putchar('-'), x=-x;
do { put[++lne]=x%10, x/=10; } while(x);
while(lne) putchar(put[lne--]^48);
putchar(ch);
}
signed main() {
read(n);
for(int i = 1; i <= n; ++i) {
scanf("%s", s[i]+1);
int ln = strlen(s[i]+1);
for(int len = 1; len <= ln; ++len)
az[i]=az[i]*base+s[i][len]-'a'+1;
if(vis.find(az[i]) == vis.end())
vis[az[i]]=i;//先统计第一个哈希值为这个的S_i的位置
}
read(q);
for(int i = 1; i <= q; ++i) {
scanf("%s", t[i]+1);
int ln = strlen(t[i]+1);
for(int o = 1; o <= ln; ++o)
bb[i]=bb[i]*base+t[i][o]-'a'+1;
if(vis.find(bb[i]) == vis.end())//找w_i,找不到就是n
to[n+1].push_back(i), ans[i]+=n;
else
to[vis[bb[i]]].push_back(i), ans[i]+=vis[bb[i]];
}
for(int i = 1; i <= n; ++i)
az[i]=0;
for(int i = 1; i <= q; ++i)
bb[i]=0;
for(int len = 1; len <= 30; ++len) {
vis.clear();
for(int i = 1; i <= q; ++i)
if(strlen(t[i]+1) >= len) //upd:!!!就是这个地方!!!一定要判
bb[i]=bb[i]*base+t[i][len]-'a'+1;//更新哈希值
for(int i = 1; i <= n; ++i) {
if(strlen(s[i]+1) < len) continue;//长度小的不算
az[i]=az[i]*base+s[i][len]-'a'+1;
++vis[az[i]];//统计个数
for(int j : to[i]) //找到w_i等于i的T_i贡献答案
if(vis.find(bb[j]) != vis.end())
ans[j]+=vis[bb[j]];//贡献答案
}
for(int j : to[n+1])//特殊处理找不到w_i的T_i
if(vis.find(bb[j]) != vis.end())
ans[j]+=vis[bb[j]];
}
for(int i = 1; i <= q; ++i)
write(ans[i], '\n');
return 0;
}