+5  A: 

Convert the set of candidate strings into a deterministic finite state automaton and then run through the input string in linear time. Converting a single string into a DFS is well-covered in the standard books. You can convert a set of strings by first constructing a non-deterministic automaton and then determinizing it. That can create exponential blow-up in the worst case in the size of the automaton but the search afterwards is fast; especially if the target string is long and the candidates short that's going to work well.

antti.huima
Isn't that what the flux capacitor is for?
Dave Swersky
+1 for mentioning FSMs. Absolutely the fastest solution.
Anton
Is this as soln as relevant given that the input strings and candidate strings are all very short e.g. < 50 chars?
Joel
@Joel I think it depends on what you mean when you write above that "I want to do this repeatedly across many input strings". The DFS does not depend on the input string, so if the set of candidate strings is constant across multiple input strings then that's equivalent to one long input string and thus the solution is definitely relevant. If all strings are short AND the candidates change every time then it might not be the optimal solution.
antti.huima
How does this compare to the Rabin-Karp multiple pattern search algo suggested above? Given the large number of possible substrings, and the relatively short inputstring length this would have seemed like a good solution?
Joel
@Joel Rabin-Karp is definitely another good solution, it just has different asymptotic behavior. The DFS solution has best asymptotic complexity for matching because it is O(n) in the length of the input string only. Rabin-Karp has extra terms in the complexity. However it is simpler to implement from scratch.
antti.huima
+8  A: 

Your best options are the Aho-Corasick algorithm and the Rabin-Karp algorithm. Because I am no Java developer I cannot tell if there are any out-of-the-box framework functions or libraries.

Just to add - if your input is not that large, you don't want to repeat the search many times and you do not have many patterns, it might be even a good idea to use a single pattern algorithm several times. The Wikipedia article on search algorithms gives many algorithms with running and preprocessing times so you can judge the options.

Daniel Brückner
Java implementation of Aho-Corasick : http://hkn.eecs.berkeley.edu/~dyoo/java/index.html
Joel
+2  A: 

You might want to look into Aho-Corasick algorithm and related algorithms. I don't know of any libraries that implement this, offhand, but this is the classic way of solving this problem.

Avi
Thx. Java implementation here: http://hkn.eecs.berkeley.edu/~dyoo/java/index.html
Joel
+5  A: 

Rabin-Karp multiple pattern search appears to be the fastest.

emptyset
+2  A: 

Also check the Boyer-Moore algorithm for single-string pattern matching.

spoulson
+5  A: 

This is what regular expressions are for. As noted above, finite state automata are what you need, but that is exactly how a standard regexp-matcher is implemented.

In java you could write something like:

StringBuilder sb = new StringBuilder();
bool first = true;
for (String subStr : substrings) {
    if (first)
        first = false;
    else
        sb.append('|');
    sb.append(escape(subStr));
}
Pattern p = Pattern.compile(sb.toString());

the method escape should escape any characters which have special meanings in a regexp.

Jørgen Fogh
why is this downvoted?
johanbev
I was wondering that too...
Joel
I can't speak for why it was down voted but I can say that due to the way Java regex is implemented, this regex can be way less efficient than searching for each substring individually.
PSpeed
I like this solution and upvoted it. However, I'd like to point out two potential problems: (1) Given a thousand or so search strings, it's possible the pattern compiler will explode. I worry memory use grows exponentially with the complexity of the match expression. (2) I believe the FSM/DFS built by the pattern compiler will on occasion back up. If it does, then one of the specialized algorithms that moves strictly forward may end up being faster yet.
Carl Smotricz
Perl it is then :)
Thorbjørn Ravn Andersen
I don't claim that my solution is perfect. It may very well be adequate though. YMMV.
Jørgen Fogh
The way regex executes a pattern like "a|b|c|d" is to start at position 0, try all options, move to position 1, try all options, move to position 2, try all options, etc.. Faster ways to do this without a big regex OR are pretty trivial to write I'd think. It will never be any worse to search all of INSTR for CAND1, then search for CAND2, etc. and will often be much better. Furthermore, that kind of search is much easier to optimize.
PSpeed
@PSpeed: I can't imagine any real regexp library being implemented like that. Anyway, if speed is really important, you might try [this library][0]. [0]: http://www.brics.dk/automaton/
Jørgen Fogh
It is though. You can look at the code for Java's regex. The issue is that the OR nodes don't know what the "a", "b", "c", etc. nodes are doing. Also, you are implicitly asking it the wrong question since "a|b|c|d" is asking for the first match of one of those... which means at the very least you will have to search for all of them before you know (unless you hit on the first character). The poster wants to know if any match at all and it's faster to test "a", "b", "c", etc. separately as compared to the regex. It always will be.
PSpeed
@Jørgen, for what it's worth, I had the exact same reaction when our regex-guru explained this to me a while back. :)
PSpeed
Java's regex may be very poorly implemented; I'm not familiar with it. But barring that, regex should give the optimal solution. The compiled regex should grow linearly in the pattern length (with any luck, sublinear), certainly not exponentially, and search time is linear.
R..
A: 

Another solution is to use a suffix array for the INSTR.
Since the INSTR is small you can sort it with bubble sort.

Afterwards you can search for a specific CAND string in O(logN) time,
where N = length(suffix_array) = length(INSTR).

Nick D
+2  A: 

We can take advantage of the small size (< 50 char) of the strings to build a super fast algo for this case, at the cost of memory.

We can hash all possible substrings of INSTR in a hash one time that will cost O(n^2) time. Then regardless of the number of CAND strings, the lookup will be O(1). Worth it for a very large number of CAND strings.

If INSTR is large, then we can build a suffix array and not sort it, so that the top item is the longest (=N) and bottom item is the last char of INSTR. Now for each CAND string, only search from the top as long as length(CAND) <= length(suffix). Each of those comparisons will be O(n).

Joy Dutta
I'm a little hazy on this so I could be off base here, but would the hash time be O(n+1)(n/2) instead of O(n^2) since thats how many different substrings that there should be?
DutrowLLC