1919import static com .indoqa .fsa .character .CharDataAccessor .*;
2020
2121import java .io .*;
22- import java .util .Arrays ;
23- import java .util .HashMap ;
24- import java .util .Map ;
25- import java .util .Map .Entry ;
26- import java .util .TreeMap ;
22+ import java .util .*;
23+ import java .util .concurrent .ConcurrentHashMap ;
2724import java .util .function .Consumer ;
2825
2926import com .indoqa .fsa .AcceptorBuilder ;
30- import com .indoqa .fsa .utils .IntList ;
31- import com .indoqa .fsa .utils .NodeData ;
3227
3328public class CharAcceptorBuilder implements AcceptorBuilder {
3429
@@ -90,16 +85,12 @@ public static CharAcceptor read(InputStream inputStream) throws IOException {
9085private static String getKey (char []node ) {
9186StringBuilder stringBuilder =new StringBuilder ();
9287
93- if (node .length >0 ) {
94- stringBuilder .append (node [0 ]);
95- }
96-
97- if (node .length >CharDataAccessor .NODE_SIZE ) {
98- stringBuilder .append (node [CharDataAccessor .NODE_SIZE ]);
99- }
88+ for (int i =0 ;i <10 ;i ++) {
89+ if (node .length <=CharDataAccessor .NODE_SIZE *i ) {
90+ break ;
91+ }
10092
101- if (node .length >CharDataAccessor .NODE_SIZE *2 ) {
102- stringBuilder .append (node [CharDataAccessor .NODE_SIZE *2 ]);
93+ stringBuilder .append (node [CharDataAccessor .NODE_SIZE *i ]);
10394 }
10495
10596stringBuilder .append ('_' );
@@ -115,10 +106,6 @@ public void addAcceptedInput(CharSequence... value) {
115106 }
116107 }
117108
118- public void addAcceptedInput (CharSequence value ) {
119- this .addAcceptedInput (value ,0 ,value .length ());
120- }
121-
122109public void addAcceptedInput (CharSequence value ,int start ,int length ) {
123110if (this .minified ||this .remapped ) {
124111throw new IllegalStateException ("The data have already been minified / remapped." );
@@ -181,6 +168,10 @@ public void write(OutputStream outputStream) throws IOException {
181168dataOutputStream .flush ();
182169 }
183170
171+ private void addAcceptedInput (CharSequence value ) {
172+ this .addAcceptedInput (value ,0 ,value .length ());
173+ }
174+
184175private void addArc (int node ,char label ,int target ,boolean terminal ) {
185176char []oldNodeData =this .nodes [node ];
186177
@@ -238,12 +229,11 @@ private boolean applyReplacements(char[] nodeData, Map<Integer, Integer> replace
238229for (int i =0 ;i <nodeData .length ;i +=CharDataAccessor .NODE_SIZE ) {
239230int target =getTarget (nodeData ,i );
240231
241- if (!replacements .containsKey (target )) {
232+ Integer replacement =replacements .get (target );
233+ if (replacement ==null ) {
242234continue ;
243235 }
244236
245- int replacement =replacements .get (target );
246-
247237boolean isTerminal =isTerminal (nodeData ,i );
248238boolean isLast =isLast (nodeData ,i );
249239
@@ -257,17 +247,23 @@ private boolean applyReplacements(char[] nodeData, Map<Integer, Integer> replace
257247return result ;
258248 }
259249
260- private void applyReplacements (Map <Integer ,Integer >replacements ) {
250+ private Set < String > applyReplacements (Map <Integer ,Integer >replacements ) {
261251this .sendMessage ("Applying " +replacements .size () +" replacements" );
262252
253+ Set <String >result =new HashSet <>();
254+
263255for (int i =0 ;i <this .nodeCount ;i ++) {
264256char []node =this .nodes [i ];
265257if (node ==null ) {
266258continue ;
267259 }
268260
269- this .applyReplacements (node ,replacements );
261+ if (this .applyReplacements (node ,replacements )) {
262+ result .add (getKey (node ));
263+ }
270264 }
265+
266+ return result ;
271267 }
272268
273269private char []buildData () {
@@ -286,8 +282,8 @@ private char[] buildData() {
286282return data ;
287283 }
288284
289- private Map <String ,IntList >buildGroups () {
290- Map <String ,IntList >result =new TreeMap <>();
285+ private Map <String ,List < Integer > >buildGroups () {
286+ Map <String ,List < Integer > >result =new TreeMap <>();
291287
292288for (int i =0 ;i <this .nodeCount ;i ++) {
293289char []node =this .nodes [i ];
@@ -297,9 +293,9 @@ private Map<String, IntList> buildGroups() {
297293
298294String key =getKey (node );
299295
300- IntList indexes =result .get (key );
296+ List < Integer > indexes =result .get (key );
301297if (indexes ==null ) {
302- indexes =new IntList ();
298+ indexes =new ArrayList <> ();
303299result .put (key ,indexes );
304300 }
305301
@@ -309,22 +305,22 @@ private Map<String, IntList> buildGroups() {
309305return result ;
310306 }
311307
312- private Map <Integer ,Integer >findReplacements (IntList group ) {
308+ private Map <Integer ,Integer >findReplacements (List < Integer > group ) {
313309Map <Integer ,Integer >result =new HashMap <>();
314310
315- Map <NodeData ,Integer >hashes =new HashMap <>(group .size ());
311+ Map <String ,Integer >hashes =new ConcurrentHashMap <>(group .size ());
316312
317313for (int i =0 ;i <group .size ();i ++) {
318- int eachIndex =group .get (i );
314+ Integer eachIndex =group .get (i );
319315char []node =this .nodes [eachIndex ];
320316if (node ==null ) {
321317continue ;
322318 }
323319
324- Integer previous =hashes .putIfAbsent (new NodeData (node ),eachIndex );
325-
320+ Integer previous =hashes .putIfAbsent (new String (node ),eachIndex );
326321if (previous !=null ) {
327322result .put (eachIndex ,previous );
323+ this .nodes [eachIndex ] =null ;
328324 }
329325 }
330326
@@ -339,31 +335,22 @@ private void minify() {
339335this .sendMessage ("Minifying " +this .nodeCount +" nodes ..." );
340336
341337Map <Integer ,Integer >replacements =this .replaceEndNodes ();
342- this .applyReplacements (replacements );
338+ Set < String > changedGroups = this .applyReplacements (replacements );
343339
344- Map <String ,IntList >groups =this .buildGroups ();
340+ Map <String ,List < Integer > >groups =this .buildGroups ();
345341
346342while (true ) {
347343replacements .clear ();
348344
349- for (IntList eachGroup :groups .values ()) {
350- if (eachGroup .size () <2 ) {
351- continue ;
352- }
353-
354- Map <Integer ,Integer >groupReplacements =this .findReplacements (eachGroup );
355- for (Entry <Integer ,Integer >eachReplacement :groupReplacements .entrySet ()) {
356- this .nodes [eachReplacement .getKey ()] =null ;
357- }
358-
359- replacements .putAll (groupReplacements );
345+ for (String eachChangedGroup :changedGroups ) {
346+ replacements .putAll (this .findReplacements (groups .get (eachChangedGroup )));
360347 }
361348
362349if (replacements .isEmpty ()) {
363350break ;
364351 }
365352
366- this .applyReplacements (replacements );
353+ changedGroups = this .applyReplacements (replacements );
367354 }
368355
369356this .minified =true ;