Change:
period = period2; } <ins> // This isn't in the original algorithm, as far as I'm aware. </ins> let byteset = needle.iter() .fold(0, |a, &b| (1 << ((b & 0x3f) as uint)) | a); <del> // The logic here (calculating crit_pos and period, the final if statement to see which // period to use for the TwoWaySearcher) is essentially an implementation of the // "small-period" function from the paper (p. 670) </del> <ins> // A particularly readable explanation of what's going on here can be found // in Crochemore and Rytter's book "Text Algorithms", ch 13. Specifically // see the code for "Algorithm CP" on p. 323. </ins> // <del> // In the paper they check whether `needle.slice_to(crit_pos)` is a suffix of // `needle.slice(crit_pos, crit_pos + period)`, which is precisely what this does </del> <ins> // What's going on is we have some critical factorization (u, v) of the // needle, and we want to determine whether u is a suffix of // v.slice_to(period). If it is, we use "Algorithm CP1". Otherwise we use // "Algorithm CP2", which is optimized for when the period of the needle // is large. </ins> if needle.slice_to(crit_pos) == needle.slice(period, period + crit_pos) { TwoWaySearcher { crit_pos: crit_pos,

Discussion:
It seems that for UTF-8 strings the find_str method can return the byte index of the first matching substring, but there is no matching substring in fact. Here's the code: Compiled with "rustc " And it returns: Which indicates that the string "hah" was found at the end of the m string, but it isn't there - the end is "jah". Rust version: rustc 0.12.0-pre-nightly ( 2014-08-28 23:56:20 +0000) 64bit OS: OS X 10.9.4
cc
Pretty weird! This also returns true: . Also, if you delete any of the numbers it gives the correct result. Also gives the correct result if you change the first 'a' or 'h'.
Is there value in switching to a simpler algorithm?
That was my thought as well. What's the fastest alternative to Two-Way thats simple to implement? Boyer-Moore-Horspool?
I don't know about fastest; would be worth researching. In any case, we currently have an algorithm that takes infinite time to get the right answer for some inputs, so even temporarily switching back to a naive search would be a speed-up (correctness trumps performance :) ).
In addition to being buggy, the current implementation of findstr seems to be very inefficient. The following Rust code: needs about x1.6 time more than it's C++ (Apple LLVM version 5.1 (clang-503.0.40) x8664-apple-darwin13.3.0) equivalent: I was thinking that it was because Rust is just much slower than C++, but what makes me think that it's find_str's fault is the fact that when I change the "contains" condition to something like this in both programs: the Rust version (surprisingly?) becomes faster - the C++ one needs x2.5 more time to execute. The average length of the "auction" string is 70 and the "t" string is 7 on average.
I'm far from an expert on string matching algorithms, but after a bit of googling I found which benchmarks 85 different algorithms.

I'm currently attempting to implement and benchmark three of them since they seem both generally fast and simple to implement: Horspool's Quick Search Tuned Boyer-Moore
The algorithm python uses for string search is pretty simple and pretty fast:
It seems to me that the naive algorithm with some optimizations (loop unrolling, code inlining, etc) gives the best results. Here's the libc++ implementation that turned out to be much faster than the Rust's one in my tests: (look for __search)
the paper you referred to seems to compare algorithms that find ALL occurrences, but we most of the time need to find only one. I'm not sure if implementing any of the algorithms you proposed in the standard library makes sense. I'd suggest using the naive algorithm, but optimize the code (unroll loops, inline code, write some unsafe code to disable bounds checks if necessary, etc). However, the algorithm used in Python might be applicable.
Please don't switch a programming environment's string matcher to anything with a quadratic worst-case. It is better to debug your implementation of two-way matching until it works. If you really, really want to switch your two-way matcher for something "simpler", the simplest thing I know that has a linear worst-case time complexity and constant storage overhead works like this: linear time and constant space, find the lexicographically largest suffix of the pattern. Write the pattern as uv, where v is the lex-largest suffix and u is the rest of the string. occurrences of v, again in linear time and constant space. (This is possible because v is lex-largest.) you find a v and it's at least len(u) characters after the last occurrence of v, check, using memcmp, that u precedes it. If it does, return a match; if not, do nothing. Step 1 is nontrivial, but it's slightly easier than two-way matching. It is Algorithm MS in Crochemore and Rytter's free "Text Algorithms" book. Steps 2 and 3 look exactly the same as two-way matching. Again, two-way matching is the way to go. Please use two-way matching for your stock string matcher, not a hacky implementation of a naive matcher or something that requires an auxiliary table!
Good idea. Maybe it's slow because it's broken.

Ideally, the performance of the implementation should be comparable to the C++ one for searching for short patterns. I can perform my tests again when you fix it.
Thanks for the pointer to the Text Algorithms book, this seems much more readable than the paper. I'm going to give debugging Two-Way a shot.
is another example that currently comes up true, for future reference.
maybe randomized testing using quick check could help here. If it can easily come up with examples for the this bug.