HDU 2846 Trie查询

给出若干模式串,再给出若干询问串,求每个询问串作为多少个模式串的子串出现。

如果一个串是另一个串的子串,则一定是另一个串某个前缀的后缀或者某个后缀的前缀。根据字典树的性质,将模式串的每一个后缀插入字典树中,同时更新字典树中节点的cnt值。这里需要注意不要重复累加贡献,可以在字典树中新增一个num的信息值来实现这一点。

 1 #include <iostream>
 2 #include <vector>
 3 #include <algorithm>
 4 #include <string>
 5 #include <string.h>
 6 #include <stdio.h>
 7 #include <queue>
 8 #include <stack>
 9 #include <map>
10 #include <set>
11 #include <cmath>
12 #include <ctime>
13 #include <cassert>
14 #include <sstream>
15 using namespace std;
16 
17 const int N=223456;
18 const int MOD=1e9+7;
19 
20 
21 const int CHARSET=26,BASE='a',MAX_NODE=10000*20*26+5000;
22 struct Trie {
23     int tot,root,child[MAX_NODE][CHARSET];
24     int flag[MAX_NODE],num[MAX_NODE];
25     Trie(){
26         init();
27     }
28     void init(){
29         tot=0;
30         root=newNode();
31     }
32     int newNode() {
33         ++tot;
34         memset(child[tot],0,sizeof(child[tot]));
35         flag[tot]=0;
36         num[tot]=-1;
37         return tot;
38     }
39     void insert(const char *str,int id){
40         int *cur=&root;
41         for (const char *p=str;*p;++p){
42             cur=&child[*cur][*p-BASE];
43             if (*cur==0){
44                 *cur=newNode();
45             }
46             if (num[*cur]!=id)
47                 flag[*cur]++;
48             num[*cur]=id;
49         }
50     }
51     int query(const char *str){
52         int *cur=&root;
53         for (const char *p=str;*p&&(*cur);++p){
54             cur=&child[*cur][*p-BASE];
55         }
56         return flag[*cur];
57     }
58 }trie;
59 int main () {
60     int n;
61     scanf("%d",&n);
62     char s[120];
63     for (int i=1;i<=n;i++) {
64         scanf("%s",s);
65         int len=strlen(s);
66         for (int j=0;j<len;j++)
67             trie.insert(s+j,i);
68     }
69     int Q;
70     scanf("%d",&Q);
71     while (Q--) {
72         scanf("%s",s);
73         int ret=trie.query(s);
74         printf("%d\n",ret);
75     }
76     return 0;
77 }
View Code

 

你可能感兴趣的:(HDU 2846 Trie查询)