HDU 2846--字典树

http://acm.hdu.edu.cn/showproblem.php?pid=2846

题意是给出一些模式串,再给出几个询问,询问给出的字符串在多少个模式串中出现

比如字符串abc所含的字串有a,ab,abc,b,bc,c

可用字典树解决,字典树能很好的处理前缀出现的次数,所以可将模式串分解,依次插入

需要注意的是对于同一个模式串的不同子串可能有相同的前缀,为了避免多次计算,可以添加字典树节点的信息,添加num记录最后插入的字符串是第num个模式串的子串。

关键在于怎么控制避免多次计算。。。

在写的时候脑残的先计数然后在进行移位,应该要反过来。。。

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 using namespace std;
 5 struct node{
 6     int num;
 7     int count;
 8     node *next[26];
 9     node()
10     {
11         num=0;
12         count=0;
13         memset(next,0,sizeof(next));
14     }
15 };
16 node *root=new node;
17 void build(char *a,int j)
18 {
19     node *p=root;
20     for(int i=0;a[i];i++)
21     {
22         int k=a[i]-'a';
23         if(p->next[k]==NULL)
24         {
25             p->next[k]=new node;
26             p=p->next[k]; //先移位,再计数
27             p->num=j;
28             p->count++;
29         }
30         else 
31         {
32             p=p->next[k];//先移位,再计数
33             if(p->num!=j)
34             {
35                 p->num=j;
36                 p->count++;
37             }
38         }
39     }
40 }
41 int Find(char *b)
42 {
43     node *p=root;
44     for(int i=0;b[i];i++)
45     {
46         int k=b[i]-'a';
47         if(p->next[k]==NULL)
48             return 0;
49         p=p->next[k];
50     }
51     return p->count;
52 }
53 int main()
54 {
55     int n,m;
56     char a[30],b[30];
57     while(~scanf("%d",&n))
58     {
59         for(int i=1;i<=n;i++)
60         {
61             scanf("%s",a);
62             for(int j=0;a[j];j++)
63                 build(&a[j],i);
64         }
65         scanf("%d",&m);
66         while(m--)
67         {
68             scanf("%s",b);
69             printf("%d\n",Find(b));
70         }
71     }
72     return 0;
73 }

 

posted on 2013-02-05 16:10  acoderworld  阅读(72)  评论(0)    收藏  举报

导航