【字典树】洛谷 P2922 [USACO08DEC]Secret Message G
维护两个数组v1[],v2[],v1[]用于标记,v2[]用于记录v1的后缀和,对于一个询问,如果在字典树上向下查找直到查找不到时,此时答案就是访问到的v1[]的和,如果查找完了,也就是说字典树上还有比询问更长的串,则答案也是访问到的v1[]的和,但是得加上此时的后缀和v2[],因为当前v2[]包含v1[],所以还得减去v1[];
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define ll long long
#define ULL unsigned long long
#define Pair pair<LL,LL>
#define ls rt<<1
#define rs rt<<1|1
#define Pi acos(-1.0)
#define eps 1e-6
#define DBINF 1e100
#define mod 998244353
#define MAXN 1e18
#define MS 150000
int n,m;
int p[500009][3];
int v1[500009];
int v2[500009];
int step;
void insert(int len){
int cc = 0;
for(int i=1;i<=len;i++){
int x;
cin >> x;
if(!p[cc][x]) p[cc][x] = ++step;
cc = p[cc][x];
v2[cc]++;
}
v1[cc]++;
}
int find(int len){
int cc = 0;
int ans = 0;
int flag = 0;
for(int i=1;i<=len;i++){
int x;
cin >> x;
if(!p[cc][x]){
flag = 1;
}
if(flag) continue;
cc = p[cc][x];
ans += v1[cc];
}
if(flag){
return ans;
}
ans += v2[cc];
ans -= v1[cc];
return ans;
}
int main() {
ios::sync_with_stdio(false);
cin >> n >> m;
for(int i=1;i<=n;i++){
int len;
cin >> len;
insert(len);
}
while(m--){
int len;
cin >> len;
cout << find(len) << "\n";
}
return 0;
}

浙公网安备 33010602011771号