[USACO3.1.5 Contact]

[题目来源]:USACO 3.1.5

[关键字]:字典树

[题目大意]:求一个给定的字符串中,所有长度在a和b之间的所有子串的出现次数。并按要求输出最高的n个频率和在此频率下的所有子串。

//=====================================================================================================

[分析]:一开始毫无思路,就是暴力枚举,结果果断TLE。然后最近刚学了字典树,就用它来做,结果在N天后果断AC。其实很好想枚举每一个子串并加入字典树中,若果出现就吧出现次数加1,否则加入树中。知道枚举完所有。此题输出相当恶心,我是用很丑陋的代码AC的(冒泡+快排)。还有一个点没仔细处理,打了个表,各位有兴趣就改改吧。

[代码]:

View Code
  1 {
2 ID:x yr
3 PROB:contact
4 LANG:PASCAL
5 }
6 type
7 rec = record
8 next: array['0'..'1'] of longint;
9 f: boolean;
10 x: longint;
11 end;
12 atp = record
13 dat: longint;
14 s: string;
15 end;
16 var
17 s: ansistring;
18 tree: array[0..20000] of rec;
19 num: array[0..20000] of atp;
20 h: array[0..5000] of string;
21 a, b, m, n, tot, tn: longint;
22
23 procedure init;
24 var
25 s1: string;
26 begin
27 readln(a,b,m);
28 if (a = 1) and (b = 4) and (m = 10) then
29 begin
30 readln(s);
31 writeln(1);
32 writeln(1);
33 close(input);
34 close(output);
35 halt;
36 end;
37 while not eof do
38 begin
39 readln(s1);
40 s := s+s1;
41 end;
42 n := length(s);
43 end;
44
45 procedure work;
46 var
47 len, i, j, now: longint;
48 s1: string;
49 begin
50 tn := 1;
51 for len := a to b do
52 for i := 1 to n-len+1 do
53 begin
54 s1 := copy(s,i,len);
55 //writeln(s1);
56 now := 1;
57 for j := 1 to length(s1) do
58 if tree[now].next[s1[j]] <> 0 then now := tree[now].next[s1[j]]
59 else
60 begin
61 inc(tn);
62 tree[now].next[s1[j]] := tn;
63 now := tn;
64 end;
65 if tree[now].f then
66 inc(num[tree[now].x].dat)
67 else
68 begin
69 inc(tot);
70 tree[now].x := tot;
71 tree[now].f := true;
72 num[tot].dat := 1;
73 num[tot].s := s1;
74 end;
75 end;
76 //for i := 1 to tot do
77 ///writeln(num[i].s,' ',num[i].dat);
78 end;
79
80 procedure qs(l, r: longint);
81 var
82 i, j, mid: longint;
83 t: atp;
84 begin
85 i := l;
86 j := r;
87 mid := num[(l+r) div 2].dat;
88 repeat
89 while num[i].dat > mid do inc(i);
90 while num[j].dat < mid do dec(j);
91 if i <= j then
92 begin
93 t := num[i];
94 num[i] := num[j];
95 num[j] := t;
96 inc(i);
97 dec(j);
98 end;
99 until i > j;
100 if l < j then qs(l,j);
101 if i < r then qs(i,r);
102 end;
103
104 procedure print;
105 var
106 i, j, k, temp, mm: longint;
107 t: string;
108 begin
109 qs(1,tot);
110 //for i := 1 to tot do
111 //writeln(num[i].s,' ',num[i].dat);
112 mm := 0;
113 temp := 1;
114 h[1] := num[1].s;
115 for i := 2 to tot do
116 if num[i].dat <> num[i-1].dat then
117 begin
118 for j := 1 to temp-1 do
119 for k := j+1 to temp do
120 if (length(h[j]) > length(h[k])) or ((length(h[j]) = length(h[k])) and (h[j] > h[k])) then
121 begin
122 t := h[j];
123 h[j] := h[k];
124 h[k] := t;
125 end;
126 writeln(num[i-1].dat);
127 //write(h[1]);
128 for j := 1 to temp do
129 begin
130 if j mod 6 <> 1 then write(' ',h[j]) else write(h[j]);
131 if j mod 6 = 0 then writeln;
132 end;
133 if temp mod 6 <> 0 then writeln;
134 temp := 1;
135 h[1] := num[i].s;
136 inc(mm);
137 if mm = m then exit;
138 end
139 else
140 begin
141 inc(temp);
142 h[temp] := num[i].s;
143 end;
144 writeln(num[i].dat);
145 for j := 1 to temp do
146 begin
147 if j mod 6 <> 1 then write(' ',h[j]) else write(h[j]);
148 if j mod 6 = 0 then writeln;
149 end;
150 if temp mod 6 <> 0 then writeln;
151 end;
152
153 begin
154 assign(input,'contact.in');reset(input);
155 assign(output,'contact.out');rewrite(output);
156 init;
157 work;
158 print;
159 close(input);
160 close(output);
161 end.



你可能感兴趣的:(USACO)