[USACO08DEC]Secret Message

OJ题号:

洛谷2922

思路:

字典树,每个结点记录经过该节点的字符串数cnt和以该结点结尾的字符串数量val。
每次询问时累加经过节点的val值和结尾结点的cnt值。

 1 #include<cstdio>
 2 #include<cctype>
 3 #include<cstring>
 4 inline int getint() {
 5     char ch;
 6     while(!isdigit(ch=getchar()));
 7     int x=ch^'0';
 8     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
 9     return x;
10 }
11 class Trie {
12     private:
13         static const int maxnode=500001;
14         int ch[maxnode][2];
15         int val[maxnode],cnt[maxnode];
16         int sz;
17     public:
18         Trie() {
19             sz=0;
20             memset(ch,0,sizeof ch);
21             memset(val,0,sizeof val);
22             memset(cnt,0,sizeof cnt);
23         }
24         void insert(int *s) {
25             int x=0,n=s[0];
26             for(int i=1;i<=n;i++) {
27                 if(!ch[x][s[i]]) {
28                     ch[x][s[i]]=++sz;
29                 }
30                 cnt[x]++;
31                 x=ch[x][s[i]];
32             }
33             val[x]++;
34         }
35         int query(int *s) {
36             int x=0,n=s[0],ans=0;
37             for(int i=1;i<=n;i++) {
38                 ans+=val[x];
39                 if(!ch[x][s[i]]) {
40                     return ans;
41                 }
42                 x=ch[x][s[i]];
43             }
44             return ans+val[x]+cnt[x];
45         }
46 };
47 Trie t;
48 int main() {
49     int m=getint(),n=getint();
50     int s[10001];
51     while(m--) {
52         s[0]=getint();
53         for(int i=1;i<=s[0];i++) s[i]=getint();
54         t.insert(s);
55     }
56     while(n--) {
57         s[0]=getint();
58         for(int i=1;i<=s[0];i++) s[i]=getint();
59         printf("%d\n",t.query(s));
60     }
61     return 0;
62 } 

 

posted @ 2017-07-30 16:21  skylee03  阅读(95)  评论(0编辑  收藏  举报