HDU 2846 字典树 非前缀子串的计数

这道题目与一般的字典树不同的是要查询的字符串不是已经插入字符串的前缀,同时也不是后缀,只需满足该字符串是其中一个商品的子串即可,考虑到既然要用i到字符串,所以对于每一个商品的字符串插入以每一个字符开头后缀,但是后来出现了一个问题,就是对于以i下标开头的子串同时是以i结尾的前面某一字符串的子串时,会出现重复计数的问题,想过在每一个节点用一个set作为经过该节点的字符串的Id号,很显然,内存超了,后来看网上说既然是要避免同一个商品的字符串出现重复问题,只需在节点标记一下经过此节点的最后的那个商品的标号,标号相同时候,count不变,不同的时候count++,这样便解决了问题。。。

View Code
 1 #include <iostream>
2 #include<stdio.h>
3 #include<string.h>
4 #include<string>
5 using namespace std;
6 struct Trie_node
7 {
8 Trie_node *next[26];
9 int count;
10 int laststr;
11 Trie_node()
12 {
13 count=0;
14 for(int i=0;i<26;i++)
15 {
16 next[i]=NULL;
17 count=0;
18 laststr=-1;
19 }
20 }
21 };
22 void insert(char *s,Trie_node *root,int id)
23 {
24 Trie_node *p=root;
25 int index;
26 while(*s)
27 {
28 index=*s-'a';
29 if(p->next[index]==NULL)
30 {
31 p->next[index]=new Trie_node();
32 }
33 p=p->next[index];
34 if((p->laststr)!=id)
35 {
36 p->count++;
37 p->laststr=id;
38 }
39 s++;
40 }
41 }
42 int find(char *s,Trie_node *root)
43 {
44 Trie_node *p=root;
45 int index;
46 while(*s)
47 {
48 index=*s-'a';
49 if(p->next[index]==NULL)return 0;
50 p=p->next[index];
51 s++;
52 }
53 return p->count;
54 }
55 int main()
56 {
57 char s[30];
58 int p,Q,len,i;
59 Trie_node *root=new Trie_node();
60 scanf("%d",&p);
61 while(p--)
62 {
63 scanf("%s",s);
64 len=strlen(s);
65 for(i=0;i<len;i++)
66 {
67 insert(s+i,root,p+1);
68 }
69 }
70 scanf("%d",&Q);
71 while(Q--)
72 {
73 scanf("%s",s);
74 printf("%d\n",find(s,root));
75 }
76 return 0;
77 }

posted on 2011-09-27 21:11  lonelycatcher  阅读(552)  评论(0编辑  收藏  举报

导航