Skip to content

Commit

Permalink
Add wildcard search
Browse files Browse the repository at this point in the history
  • Loading branch information
rpereira committed Jun 25, 2016
1 parent 712282e commit f63cf7d
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 0 deletions.
5 changes: 5 additions & 0 deletions examples/TrieExample.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,10 @@ public static void main(String[] args) {
System.out.println("Longest prefix of \"peckleton\":");
System.out.println("* " + st.longestPrefixOf("peckleton"));
System.out.println();

System.out.println("Keys that match pattern \"p**er\":");
for (String key : st.wildKeys("p**er")) {
System.out.println("* " + key);
}
}
}
47 changes: 47 additions & 0 deletions src/main/java/TrieST.java
Original file line number Diff line number Diff line change
Expand Up @@ -323,4 +323,51 @@ private int search(Node x, String query, int d, int length) {

return search(x.next[c], query, d + 1, length);
}

/**
* Returns all of the keys in the symbol table that match the specified
* pattern, where '_' character is treated as a wildcard character.
*
* @param pattern the pattern to match
* @return all of the keys in the symbol table that match pattern, as an
* iterable, where '_' is treated as a wildcard character.
*/
public Iterable<String> wildKeys(String pattern) {
Queue<String> queue = new LinkedList<String>();
wildCollect(root, "", pattern, queue);
return queue;
}

/**
* Similar idea to the one used in collect(), but adds an argument specifying
* the pattern to collect and also adds a test to make a recursive call for
* all links when the pattern char is a wildcard or only for the link
* corresponding to the pattern charecter.
*/
private void wildCollect(Node x, String prefix, String pattern, Queue<String> q) {
if (x == null) {
return ;
}

int prefixLength = prefix.length();
int patternLength = pattern.length();

if (prefixLength == patternLength && x.value != null) {
q.add(prefix);
}

// No need to consider keys longer than pattern
if (prefixLength == patternLength) {
return;
}

// TODO: a prefix of type StringBuilder instead of string would be more
// efficient. It will do for now.
char next = pattern.charAt(prefixLength);
for (char c = 0; c < R; c++) {
if (next == '*' || next == c) {
wildCollect(x.next[c], prefix + c, pattern, q);
}
}
}
}
18 changes: 18 additions & 0 deletions src/test/java/TrieSTTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -213,4 +213,22 @@ public void testNonexistentLongestPrefixOf() {
TrieST<Integer> st = buildDefaultTrieST();
assertEquals("", st.longestPrefixOf("quicksort"));
}

@Test
public void testWildKeys() {
TrieST<Integer> st = buildDefaultTrieST();
Iterable<String> keysIter = st.wildKeys("p**er");
Queue<String> keys = new LinkedList<String>();
Queue<String> expectedKeys = new LinkedList<String>();

expectedKeys.add("peter");
expectedKeys.add("piper");

for (String key : keysIter) {
keys.add(key);
}

// Specifying an empty string should return all keys
assertEquals(expectedKeys, keys);
}
}

0 comments on commit f63cf7d

Please sign in to comment.