字典树
把所有信息建一个字典树
然后把每条密码在字典树上跑一遍
把经过的结束标记以及跑到的最后的一个节点的整个子树的结束标记加起来
开一个数组存一下每个节点的子树的结束标记和就好了
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; const int N=1e5+7; const int M=1e6+7; int n,m,l; long long ans,sum[M],p[M]; //p是结束标记,sum是子树总的结束标记 int ch[M][2],cnt; char s[N]; void add(int x,int k) //k表示当前加到了第k个字符 { sum[x]++; if(k==l) { p[x]++; return; } int v=s[k]-'0'; if(!ch[x][v]) ch[x][v]=++cnt; add(ch[x][v],k+1); } void query(int x,int k) //k表示当前跑到了第k个字符 { if(k==l)//如果到了最后一个节点 { ans+=sum[x];//加上整个子树的标记 return; } ans+=p[x];//加上经过的结束标记 int v=s[k]-'0'; if(!ch[x][v]) return; query(ch[x][v],k+1);//向下跑 } int main() { cin>>n>>m; for(int i=1;i<=n;i++) { scanf("%d",&l); for(int i=0;i<l;i++) scanf("%s",&s[i]); add(0,0); } for(int i=1;i<=m;i++) { scanf("%d",&l); for(int i=0;i<l;i++) scanf("%s",&s[i]); ans=0; query(0,0); printf("%lld ",ans); } return 0; }