zoj 3228 Searching the String 字典树的应用

【题意】给出一串主串,然后下面有n串模式串,模式串前面有一个值,
                0:在主串中有多少串该模式串,假如aaa 找aa,那么就有2串
                1:在主串中有多少串该模式串,并且不能有重叠部分,假如aaa找aa,那么只有1串

 

首先对长串分割,建立trie树,这样从字符串上任意一个位置开始的长度不超过6的子串都记录下来了。对于可以重叠的子串的数量,直接对一个原有的节点上的记录的数+1即可;对于不能重叠的,就要用到刚才那个“记录每个单词最后出现的pos”了,看这个状态节点最后出现的位置是否与当前看到的有重叠,没有才能对那个数字+1并更新节点位置。

 

 

View Code
 1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 using namespace std;
5 const int N=100010;
6 const int kind=26;
7 struct TRIE{
8 int next[kind];
9 int overlap,nonoverlap;
10 int end;
11 void init()
12 {
13 memset(next,0,sizeof(next));
14 overlap=nonoverlap=0;
15 end=-1;
16 }
17 }trie[N*6];
18 int root,tot;
19 char str[N];
20
21 void init()
22 {
23 root=tot=0;
24 trie[root].init();
25 }
26
27 void insert(char *s,int pos)
28 {
29 int r,i=0,index;
30 r=0;
31 while(s[i])
32 {
33 index=s[i]-'a';
34 if(!trie[r].next[index])
35 {
36 trie[++tot].init();
37 trie[r].next[index]=tot;
38 }
39 r=trie[r].next[index];
40 trie[r].overlap++;
41 if(trie[r].end<pos)
42 {
43 trie[r].nonoverlap++;
44 trie[r].end=pos+i;
45 }
46 i++;
47 }
48 }
49 void query(int op,char *s)
50 {
51 int i=0,index,r;
52 r=0;
53 while(s[i])
54 {
55 index = s[i] - 'a';
56 if(!trie[r].next[index])
57 {
58 printf("0\n");
59 return ;
60 }
61 r=trie[r].next[index];
62 i++;
63 }
64 if(op==0)
65 printf("%d\n",trie[r].overlap);
66 else if(op==1)
67 printf("%d\n",trie[r].nonoverlap);
68
69 }
70
71 int main()
72 {
73 int i,j,q,op,len,cas=1;
74 char sub[10];
75 while(scanf("%s",str)!=EOF)
76 {
77 init();
78 len=strlen(str);
79 for(i=0;i<len;i++)
80 {
81 for(j=0;j<6 && i+j<len;j++)
82 sub[j]=str[i+j];
83 sub[j]=0;
84 insert(sub,i);
85 }
86 scanf("%d",&q);
87 printf("Case %d\n",cas++);
88 for(i=0;i<q;i++)
89 {
90 scanf("%d%s",&op,sub);
91 query(op,sub);
92 }
93 printf("\n");
94 }
95 return 0;
96 }


 

 

 

 

 

posted on 2012-03-10 20:24  孤星_bin  阅读(348)  评论(0编辑  收藏  举报

导航