Once we know that an item is a match point that isn't contained within another match point, its going to be a match point in any recursive step we run.

I tried caching the Edit here indexed by bOf(rec), so that on recursive steps we didn't need to redo the stretching of a match to determine its total length.  Unfortunately that proved to be slower than not caching at all.  Like the isUnique() caching below I think this is being caused by the input sequence having too cheap of an equals() method.

FWIW, I tried caching in a HashMap<Integer,Edit>, and also in a sorted list of Edit (sorted by startB).  The latter seemed like a good idea because the match list is already sorted, so we could merge-join the two lists together in this loop.  I suspect the caching was slower because of the amount of memory being allocated to track the Edit instances.

So then I went and removed use of Edit for region and index throughout the code, so that we didn't do memory allocations at all.  That was even slower than using the Edit instances, as apparently pushing 8 ints onto the call stack during each frame activation was slower than allocating the two objects and pushing only those two references onto the stack.  Yuck.