1- using System ;
2-
3- namespace String ;
1+ namespace Bor ;
42
53/// <summary>
64/// A class representing the bor data structure
7- /// The bor can store Latin alphabet characters, numbers
85/// </summary>
96public class Bor
107{
@@ -13,23 +10,18 @@ public class Bor
1310 /// </summary>
1411 private class Node
1512 {
16- /// <summary>
17- /// Array of vertices to move from one vertex to another
18- /// The bor can store Latin alphabet characters, numbers
19- /// </summary>
20- public Node ? [ ] next = new Node [ 'z' ] ;
21-
22- // A field for storing information about whether a character is the end of a string
23- public bool isTerminal { get ; set ; }
13+ // Dictionary for storing characters for each node
14+ public Dictionary < char , Node > Nodes = new ( ) ;
2415
25- // A field for storing information about the number of strings containing a certain prefix
26- public int numberOfLinesContainingThePrefix { get ; set ; }
16+ // Node property - whether it is the end of a string
17+ public bool IsTerminal { get ; set ; }
2718 }
2819
29- private Node root = new Node ( ) ;
20+ // Bor root
21+ private readonly Node root = new ( ) ;
3022
3123 // Bor size
32- private int size ;
24+ public int Size { get ; private set ; }
3325
3426 /// <summary>
3527 /// Function for adding a string
@@ -38,49 +30,31 @@ private class Node
3830 /// <returns> Was there an element string before calling Add </returns>
3931 public bool Add ( string element )
4032 {
41- Node ? node = root ;
42- int counter = 0 ;
43- for ( int i = 0 ; i < element . Length ; i ++ )
33+ if ( Contains ( element ) )
4434 {
45- if ( element [ i ] > 'z' )
46- {
47- throw new Exception ( "The bor can store Latin alphabet characters, numbers" ) ; ;
48- }
49- if ( node != null && node . next [ element [ i ] ] == null )
50- {
51- node . next [ element [ i ] ] = new Node ( ) ;
52- size ++ ;
53- }
54- else
55- {
56- counter ++ ;
57- }
58- if ( node != null )
59- {
60- node = node . next [ element [ i ] ] ;
61- if ( node != null )
62- {
63- node . numberOfLinesContainingThePrefix ++ ;
64- }
65- }
35+ return false ;
6636 }
67- if ( counter == element . Length && node != null && node . isTerminal )
37+
38+ Node node = root ;
39+ for ( int i = 0 ; i < element . Length ; i ++ )
6840 {
69- Node ? newNode = root ;
70- for ( int i = 0 ; i < element . Length ; i ++ )
41+ if ( node != null && ! node . Nodes . ContainsKey ( element [ i ] ) )
7142 {
72- newNode = newNode ? . next [ element [ i ] ] ;
73- if ( newNode != null )
74- {
75- newNode . numberOfLinesContainingThePrefix -- ;
76- }
43+ node . Nodes . Add ( element [ i ] , new Node ( ) ) ;
44+ Size ++ ;
45+ }
46+
47+ if ( node != null && node . Nodes . ContainsKey ( element [ i ] ) )
48+ {
49+ node = node . Nodes [ element [ i ] ] ;
7750 }
78- return false ;
7951 }
52+
8053 if ( node != null )
8154 {
82- node . isTerminal = true ;
55+ node . IsTerminal = true ;
8356 }
57+
8458 return true ;
8559 }
8660
@@ -94,34 +68,49 @@ public bool Contains(string element)
9468 Node ? node = root ;
9569 for ( int i = 0 ; i < element . Length ; i ++ )
9670 {
97- node = node . next [ element [ i ] ] ;
98- if ( node == null )
71+ if ( node . Nodes . TryGetValue ( element [ i ] , out node ) )
9972 {
100- return false ;
73+ continue ;
10174 }
75+
76+ return false ;
10277 }
103- return node . isTerminal ;
78+
79+ return node . IsTerminal ;
10480 }
10581
10682 /// <summary>
10783 /// Function for finding the number of strings starting with a prefix
108- /// </summary>Количество строк содеражащих префикс
84+ /// </summary>
10985 /// <returns> The number of strings starting with the prefix </returns>
11086 public int HowManyStartWithPrefix ( string prefix )
11187 {
11288 Node ? node = root ;
113- for ( int i = 0 ; i < prefix . Length ; i ++ )
89+ for ( int i = 0 ; i < prefix . Length ; i ++ )
11490 {
115- if ( node ? . next [ prefix [ i ] ] != null )
116- {
117- node = node . next [ prefix [ i ] ] ;
118- }
119- else
91+ if ( node != null )
12092 {
121- return 0 ;
93+ if ( node . Nodes . TryGetValue ( prefix [ i ] , out node ) )
94+ {
95+ continue ;
96+ }
12297 }
98+
99+ return 0 ;
100+ }
101+
102+ if ( node == null )
103+ {
104+ return 0 ;
123105 }
124- return node == null ? 0 : node . numberOfLinesContainingThePrefix ;
106+
107+ return node . IsTerminal ? 1 + node . Nodes . Count : node . Nodes . Count ;
108+ }
109+
110+ // Function for clearing dictionaries
111+ static private void ClearDictionaryAndNode ( Node node )
112+ {
113+ node . Nodes . Clear ( ) ;
125114 }
126115
127116 /// <summary>
@@ -131,49 +120,50 @@ public int HowManyStartWithPrefix(string prefix)
131120 /// <returns> as there an element string before calling Remove </returns>
132121 public bool Remove ( string element )
133122 {
134- if ( ! this . Contains ( element ) )
123+ if ( ! Contains ( element ) )
135124 {
136125 return false ;
137126 }
138- Node ? node = root ;
139- Node ? nodeWithMaxPrefix = root ;
127+
128+ int index = 0 ;
129+ Node node = root ;
130+ Node ? anotherNode = null ;
140131 for ( int i = 0 ; i < element . Length ; i ++ )
141132 {
142- node = node ? . next [ element [ i ] ] ;
143- if ( node != null )
144- {
145- node . numberOfLinesContainingThePrefix -- ;
146- }
147- if ( i == element . Length - 1 )
133+ if ( node != null )
148134 {
149- nodeWithMaxPrefix . isTerminal = false ;
135+ node = node . Nodes [ element [ i ] ] ;
136+
137+ if ( node . Nodes . Count == 0 && i == element . Length - 1 )
138+ {
139+ if ( anotherNode != null )
140+ {
141+ ClearDictionaryAndNode ( anotherNode ) ;
142+ Size -= i - index ;
143+ return true ;
144+ }
145+ else
146+ {
147+ ClearDictionaryAndNode ( root ) ;
148+ Size = 0 ;
149+ return true ;
150+ }
151+ }
152+
153+ if ( node . Nodes . Count != 0 && i == element . Length - 1 )
154+ {
155+ node . IsTerminal = false ;
156+ return true ;
157+ }
150158 }
151- }
152- node = root ;
153- for ( int i = 0 ; i < element . Length ; i ++ )
154- {
155- nodeWithMaxPrefix = node ;
156- node = node ? . next [ element [ i ] ] ;
157- if ( nodeWithMaxPrefix ? . next [ element [ i ] ] ? . numberOfLinesContainingThePrefix == 0 )
159+
160+ if ( node != null && node . IsTerminal )
158161 {
159- nodeWithMaxPrefix . next [ element [ i ] ] = null ;
162+ index = i ;
163+ anotherNode = node ;
160164 }
161165
162166 }
163167 return true ;
164168 }
165-
166- /// <summary>
167- /// Function for returning the number of elements
168- /// </summary>
169- /// <returns> Number of elements contained in the bor </returns>
170- public int Size ( )
171- {
172- return this . size ;
173- }
174-
175- static void Main ( string [ ] args )
176- {
177- return ;
178- }
179169}
0 commit comments