12
12
import java .util .Collections ;
13
13
import java .util .HashSet ;
14
14
import java .util .IdentityHashMap ;
15
- import java .util .Iterator ;
16
15
import java .util .LinkedList ;
17
16
import java .util .List ;
18
17
import java .util .Map ;
44
43
public class SetBackwardOracleMatching implements StringSearchAlgorithm {
45
44
46
45
private CharMapping mapping ;
47
- private CharWordSet <List < char []> > trie ;
46
+ private CharWordSet <char [][] > trie ;
48
47
private int minLength ;
49
48
50
49
public SetBackwardOracleMatching (Collection <String > patterns ) {
@@ -58,22 +57,22 @@ public SetBackwardOracleMatching(Collection<String> patterns, CharMapping mappin
58
57
this .trie = computeTrie (normalized (mapping , charpatterns ), minLength , mapping );
59
58
}
60
59
61
- private List < char []> normalized (CharMapping mapping , List <char []> charpatterns ) {
60
+ private char [][] normalized (CharMapping mapping , List <char []> charpatterns ) {
62
61
List <char []> normalized = new ArrayList <>(charpatterns .size ());
63
62
for (char [] cs : charpatterns ) {
64
63
normalized .add (mapping .normalized (cs ));
65
64
}
66
- return normalized ;
65
+ return normalized . toArray ( new char [ 0 ][]) ;
67
66
}
68
67
69
- private static CharWordSet <List < char []>> computeTrie (List < char []> charpatterns , int length , CharMapping mapping ) {
70
- CharWordSetBuilder <List < char []> , CharDawg <List < char []>>> builder = new CharWordSetBuilder <>(new LinkedCharDawgCompiler <List < char []> >(), new MergePatterns ());
68
+ private static CharWordSet <char [][]> computeTrie (char [][] charpatterns , int length , CharMapping mapping ) {
69
+ CharWordSetBuilder <char [][] , CharDawg <char [][]>> builder = new CharWordSetBuilder <>(new LinkedCharDawgCompiler <char [][] >(), new MergePatterns ());
71
70
72
71
for (char [] pattern : charpatterns ) {
73
72
char [] prefix = copyOfRange (pattern , 0 , length );
74
73
char [] reversePrefix = revert (prefix );
75
74
char [] suffix = copyOfRange (pattern , length , pattern .length );
76
- builder .extend (reversePrefix , asList ( prefix , suffix ) );
75
+ builder .extend (reversePrefix , new char [][] { prefix , suffix } );
77
76
}
78
77
builder .work (new BuildOracle ());
79
78
builder .work (new UseCharClasses (mapping ));
@@ -96,43 +95,53 @@ public String toString() {
96
95
return getClass ().getSimpleName ();
97
96
}
98
97
99
- public static class MergePatterns implements JoinStrategy <List < char []> > {
98
+ public static class MergePatterns implements JoinStrategy <char [][] > {
100
99
101
100
@ Override
102
- public List < char []> join (List < char []> existing , List < char []> next ) {
101
+ public char [][] join (char [][] existing , char [][] next ) {
103
102
if (existing == null ) {
104
- return new ArrayList <>( next ) ;
103
+ return next ;
105
104
} else {
106
- existing .add (next .get (1 ));
107
- return existing ;
105
+ char [][] result = new char [existing .length + 1 ][];
106
+ char [] insert = next [1 ];
107
+ int i = 1 ;
108
+ while (i < existing .length && existing [i ].length > insert .length ) {
109
+ i ++;
110
+ }
111
+ System .arraycopy (existing , 0 , result , 0 , i );
112
+ result [i ] = insert ;
113
+ if (i < existing .length ) {
114
+ System .arraycopy (existing , i , result , i + 1 , existing .length - i );
115
+ }
116
+ return result ;
108
117
}
109
118
}
110
119
111
120
}
112
121
113
- public static class BuildOracle implements CharTask <List < char []> > {
114
- private Map <CharNode <List < char []>> , CharNode <List < char []> >> oracle ;
115
- private CharNode <List < char []> > init ;
122
+ public static class BuildOracle implements CharTask <char [][] > {
123
+ private Map <CharNode <char [][]> , CharNode <char [][] >> oracle ;
124
+ private CharNode <char [][] > init ;
116
125
117
126
public BuildOracle () {
118
127
oracle = new IdentityHashMap <>();
119
128
}
120
129
121
130
@ Override
122
- public List <CharNode <List < char []>>> init (CharNode <List < char []> > root ) {
131
+ public List <CharNode <char [][]>> init (CharNode <char [][] > root ) {
123
132
this .init = root ;
124
133
return asList (root );
125
134
}
126
135
127
136
@ Override
128
- public List <CharNode <List < char []>>> process (CharNode <List < char []> > node ) {
129
- List <CharNode <List < char []> >> nexts = new ArrayList <>();
137
+ public List <CharNode <char [][]>> process (CharNode <char [][] > node ) {
138
+ List <CharNode <char [][] >> nexts = new ArrayList <>();
130
139
for (char c : node .getAlternatives ()) {
131
- CharNode <List < char []> > current = node .nextNode (c );
140
+ CharNode <char [][] > current = node .nextNode (c );
132
141
133
- CharNode <List < char []> > down = oracle .get (node );
142
+ CharNode <char [][] > down = oracle .get (node );
134
143
while (down != null ) {
135
- CharNode <List < char []> > next = down .nextNode (c );
144
+ CharNode <char [][] > next = down .nextNode (c );
136
145
if (next != null ) {
137
146
oracle .put (current , next );
138
147
break ;
@@ -150,35 +159,35 @@ public List<CharNode<List<char[]>>> process(CharNode<List<char[]>> node) {
150
159
}
151
160
152
161
@ SuppressWarnings ("unchecked" )
153
- private void addNextNode (CharNode <List < char []>> node , char c , CharNode <List < char []> > next ) {
154
- ((CharConnectionAdaptor <List < char []> >) node ).addNextNode (c , next );
162
+ private void addNextNode (CharNode <char [][]> node , char c , CharNode <char [][] > next ) {
163
+ ((CharConnectionAdaptor <char [][] >) node ).addNextNode (c , next );
155
164
}
156
165
}
157
166
158
- public static class UseCharClasses implements CharTask <List < char []> > {
167
+ public static class UseCharClasses implements CharTask <char [][] > {
159
168
160
169
private CharMapping mapping ;
161
- private Set <CharNode <List < char []> >> done ;
170
+ private Set <CharNode <char [][] >> done ;
162
171
163
172
public UseCharClasses (CharMapping mapping ) {
164
173
this .mapping = mapping ;
165
174
this .done = new HashSet <>();
166
175
}
167
176
168
177
@ Override
169
- public List <CharNode <List < char []>>> init (CharNode <List < char []> > root ) {
178
+ public List <CharNode <char [][]>> init (CharNode <char [][] > root ) {
170
179
if (mapping == CharMapping .IDENTITY ) {
171
180
return Collections .emptyList ();
172
181
}
173
182
return asList (root );
174
183
}
175
184
176
185
@ Override
177
- public List <CharNode <List < char []>>> process (CharNode <List < char []> > node ) {
178
- List <CharNode <List < char []> >> nexts = new ArrayList <>();
186
+ public List <CharNode <char [][]>> process (CharNode <char [][] > node ) {
187
+ List <CharNode <char [][] >> nexts = new ArrayList <>();
179
188
180
189
for (char c : node .getAlternatives ()) {
181
- CharNode <List < char []> > next = node .nextNode (c );
190
+ CharNode <char [][] > next = node .nextNode (c );
182
191
for (char cc : mapping .map (c )) {
183
192
addNextNode (node , cc , next );
184
193
}
@@ -191,8 +200,8 @@ public List<CharNode<List<char[]>>> process(CharNode<List<char[]>> node) {
191
200
}
192
201
193
202
@ SuppressWarnings ("unchecked" )
194
- private void addNextNode (CharNode <List < char []>> node , char c , CharNode <List < char []> > next ) {
195
- ((CharConnectionAdaptor <List < char []> >) node ).addNextNode (c , next );
203
+ private void addNextNode (CharNode <char [][]> node , char c , CharNode <char [][] > next ) {
204
+ ((CharConnectionAdaptor <char [][] >) node ).addNextNode (c , next );
196
205
}
197
206
}
198
207
@@ -202,10 +211,10 @@ private static class Finder extends AbstractStringFinder {
202
211
private final int lookahead ;
203
212
private final CharMapping mapping ;
204
213
private CharProvider chars ;
205
- private CharAutomaton <List < char []> > cursor ;
214
+ private CharAutomaton <char [][] > cursor ;
206
215
private Queue <StringMatch > buffer ;
207
216
208
- public Finder (CharWordSet <List < char []> > trie , int minLength , CharMapping mapping , CharProvider chars , StringFinderOption ... options ) {
217
+ public Finder (CharWordSet <char [][] > trie , int minLength , CharMapping mapping , CharProvider chars , StringFinderOption ... options ) {
209
218
super (options );
210
219
this .minLength = minLength ;
211
220
this .lookahead = minLength - 1 ;
@@ -241,12 +250,11 @@ public StringMatch findNext() {
241
250
long currentWindowEnd = currentWindowStart + minLength ;
242
251
char [] matchedPrefix = chars .between (currentPos , currentWindowEnd );
243
252
if (success && j < 0 ) {
244
- List <char []> patterns = cursor .iterator ().next ();
245
- Iterator <char []> iPatterns = patterns .iterator ();
246
- char [] prefix = iPatterns .next ();
253
+ char [][] patterns = cursor .iterator ().next ();
254
+ char [] prefix = patterns [0 ];
247
255
if (Arrays .equals (prefix , mapping .normalized (matchedPrefix ))) {
248
- while ( iPatterns . hasNext () ) {
249
- char [] suffix = iPatterns . next () ;
256
+ for ( int i = 1 ; i < patterns . length ; i ++ ) {
257
+ char [] suffix = patterns [ i ] ;
250
258
long currentWordEnd = currentWindowEnd + suffix .length ;
251
259
if (!chars .finished ((int ) (currentWordEnd - currentWindowStart - 1 ))) {
252
260
char [] matchedSuffix = chars .between (currentWindowEnd , currentWordEnd );
0 commit comments