BZOJ1590: [Usaco2008 Dec]Secret Message 秘密信息
给n<=50000条01串,m<=50000个询问,每次给出一个01串求有多少个n条中有多少是它的前缀以及它是多少条的前缀。
前缀?Trie!匹配时记一路上单词节点的总量加上最后一个节点子树中单词节点总量即可。
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #include<math.h> 5 //#include<iostream> 6 using namespace std; 7 8 int n,m; 9 #define maxn 500011 10 bool a[maxn];int len; 11 struct Trie 12 { 13 int ch[maxn][2],size; 14 int val[maxn],tot[maxn]; 15 Trie() {size=0;ch[0][0]=ch[0][1]=0;} 16 void insert() 17 { 18 int now=0; 19 for (int i=1;i<=len;i++) 20 { 21 if (!ch[now][a[i]]) 22 { 23 size++; 24 val[size]=0; 25 tot[size]=0; 26 ch[now][a[i]]=size; 27 ch[size][0]=ch[size][1]=0; 28 } 29 now=ch[now][a[i]]; 30 tot[now]++; 31 } 32 val[now]++; 33 } 34 int find() 35 { 36 int now=0,ans=0; 37 for (int i=1;i<=len;i++) 38 { 39 if (!ch[now][a[i]]) return ans; 40 now=ch[now][a[i]]; 41 ans+=val[now]; 42 } 43 return ans+tot[now]-val[now]; 44 } 45 }t; 46 int x; 47 int main() 48 { 49 scanf("%d%d",&n,&m); 50 for (int i=1;i<=n;i++) 51 { 52 scanf("%d",&len); 53 for (int j=1;j<=len;j++) scanf("%d",&x),a[j]=x; 54 t.insert(); 55 } 56 for (int i=1;i<=m;i++) 57 { 58 scanf("%d",&len); 59 for (int j=1;j<=len;j++) scanf("%d",&x),a[j]=x; 60 printf("%d\n",t.find()); 61 } 62 return 0; 63 }