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 }
View Code

 

posted @ 2017-08-31 13:06  Blue233333  阅读(241)  评论(0编辑  收藏  举报