并不是统计恰好匹配,而是部分匹配,可能是目标字符串短,也可能目标字符串长,可以多开一个数组记录途中每个字符串有多少个字符串经过,同时统计以某个字符结尾的字符串个数,然后在查询时就可以边查询边加上以当前字符结尾的字符串,也就是比目标字符串短并且匹配的字符串,然后在匹配成功后,再加上以当前结尾字符串的经过数量,因为经过的和结尾的是重复的,所以还要减去当前结尾的数量。
#include
using namespace std;
const int N = 1e6 + 10;
int son[N][2];
int vis[N];
int sum[N];
int idx;
void insert(string s) {
int p = 0;
for(int i = 0; i < s.size(); i ++) {
int c = s[i] - '0';
if(!son[p][c]) son[p][c] = ++ idx;
p = son[p][c];
sum[p] ++;
}
vis[p] ++;
}
int query(string s) {
int ans = 0;
int p = 0;
for(int i = 0; i < s.size(); i ++) {
int c = s[i] - '0';
if(!son[p][c]) return ans;
p = son[p][c];
ans += vis[p];
}
ans += sum[p] - vis[p];
return ans;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int m, n;
cin >> m >> n;
for(int i = 0; i < m; i ++) {
string s;
int k;
cin >> k;
while(k --) {
string x;
cin >> x;
s += x;
}
insert(s);
}
for(int i = 0; i < n; i ++) {
string s;
int k;
cin >> k;
while(k --) {
string x;
cin >> x;
s += x;
}
cout << query(s) << "\n";
}
}