HDU 2846 Repository(字典树)

嗯...

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2846

这与裸的字典树略有差别:

因为题目要求有n个字符串,m个询问  问字符串在n个字符串中出现过多少次,

即为一个字串的问题,所以我们把一个字符串拆开分别建树。

eg:

 abcd 中有a,b,c,d,abcd,bcd,cd,bc,abc...

我们可以将abcd拆成abcd bcd cd d 分别建树
 
注意:
abab会导致重复,所以用flag标记:若此编号不同于所给编号(此后缀在本要查的字符串中没有)才加1,这样就避免了重复。
 
 
AC代码:
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 
 5 using namespace std;
 6 
 7 int ch[500005][30];
 8 int flag[500005];
 9 int val[500005];
10 int cnt = 1;
11 
12 inline int ids(char c){
13     return c - 'a';
14 }
15 
16 inline void build(char *s, int k){
17     int u = 0;
18     int len = strlen(s);
19     for(int i = 0; i < len; i++){
20         int id = ids(s[i]);
21         if(!ch[u][id]) ch[u][id] = cnt++;
22         u = ch[u][id];
23         if(flag[u] != k){
24             val[u]++;
25             flag[u] = k;
26         }
27     }
28 }
29 
30 inline int query(char *s){
31     int len = strlen(s);
32     int u = 0;
33     for(int i = 0; i < len; i++){
34         int id = ids(s[i]);
35         if(!ch[u][id]) return 0;
36         u = ch[u][id];
37     }
38     return val[u];
39 }
40 
41 int main(){
42     int p, q;
43     char s[25];
44     scanf("%d", &p);
45     memset(flag, -1, sizeof(flag));
46     for(int i = 1; i <= p; i++){
47         scanf("%s", s);
48         int len = strlen(s);
49         for(int j = 0; j < len; j++)
50             build(s + j, i);
51     }
52     scanf("%d", &q);
53     for(int i = 0; i < q; i++){
54         scanf("%s", s);
55         printf("%d\n", query(s));
56     }
57     return 0;
58 }
AC代码

猜你喜欢

转载自www.cnblogs.com/New-ljx/p/11729682.html