I'm looking for robust code to solve the "Longest Common Substring" problem. I can just code it up from that description, but I'd thought I'd ask here, first, in case someone knows of an implementation either distributed with Mathematica or available from an open source. I found a hint here that a solution might be part of the (huge) Combinatorica package, but a quick search of the documentation did not disclose it.
|
|
||||
|
Mathematica supports two related functions,
while the second function is constrained to give the longest contiguous sequence:
These functions became available only in version seven; if you need to do this in an earlier version, István's routine is useful. |
|||||||||||||||||
|
Preamble and motivationWhile I am much late to the party here, I hope this answer will not be totally useless. This is a first in a series of posts where I will advocate a wider use of Java in our workflow, and present/describe certain toolset to reduce the mental overhead of this. So, my motivation here is not to provide a faster or more elegant solution, but to show that often, we can mindlessly reuse existing (found on the web or elsewhere) Java code, and the process can be made easy and painless. Simplistic Java reloaderHere I will present a simplistic Java class reloader, which takes a string of Java code, attempts to compile it, and, upon success, load the resulting class into Mathematica via Note that it is not my intention to present and describe a full workflow involving the reloader, in this post - I will save this for a future one. Here, I just present the code and an example of how it is useful for the case at hand. Code
NotesNote that you can either put this into a separate package file, or simply copy and paste into the FrontEnd, and run from there, for a quick test. The package works by saving the string with your Java code into a temporary file, and then invoking Java compiler which comes with the JRE bundled with Mathematica, to compile this class. The compiled class is stored in another temporary location, from where it is then loaded by JLink. In case if compilation errors were encountered, the message generated by Java compiler is printed, and One important limitation is that The case at handWe will now apply the above to our case. First, we need the solution for the longest common substring problem in Java. Stealing code from the webI won't stay noble and code that myself. The whole point is - why doing so if we can steal it from someone :)? I get the one from here (the second one). In the simplified workflow I am presenting now, we need a string of Java code, so we define:
Compiling and runningFirst, we have to compile and load this code:
We are now ready to use the function, no other preparation needed! For example:
Note that, since the function Now, some benchmarks:
Here we use the Mathematica's built-in function:
Now our function:
We see that our function is about 4 times slower, but, given that the Mathematica's built-in function was written in C and heavily optimized, while I just picked the first code snippet on the web I found, I think that the pain/gain ratio is pretty good. ConclusionsI tried here to make a case for using Java in our workflow more frequently. The good thing about Java is that, in contrast to MathLink/LibraryLink, the JLink interface brings us pretty much all the way there, so there is no preparation at all necessary. The Java class reloader I presented here is very simplistic, but it nevertheless "closes the circle", and now we can protptype everything exclusively from Mathematica. I will expand on this in some future posts, and illustrate the workflow more fully. Note that I don't consider the reloader as anything complete - this is rather a proof of concept at this point. For the case at hand, it took me literally 5 minutes from start to finish to get this working (the Java reloader I already had), and that includes finding the code on the web, pasting to Mathematica, compiling and using it. Given that there are many cases when Mathematica built-in functions are not available, while Java implementations are ubiquitous, I think this option can significantly expand our possibilities. Of course, to use this one needs some knowledge of Java, but let this not put you off: the things about Java you really need to know for such cases can be picked up in a day or two, especially if you have any experience in C/C++ (but even if not). |
|||||||||||||||||||||
|
|
Also, using pattern matching,just in case:
Edit With this approach you can do one thing that seems not trivial by using the faster
|
|||||
|
|
These things I have coded up before Mathematica 7 and the introduction of the built in function
Or you can just calculate the length, which is faster:
Example usage:
Note that
|
||||
|
|

LongestCommonSubsequence[]? – J. M.♦ May 28 '12 at 16:51LongestCommonSubsequenceonly returns the first hit. That might not be robust enough as there could be multiple distinct and different hits. – István Zachar May 28 '12 at 17:14tutorial/StringPatterns,tutorial/WorkingWithStringPatterns, andguide/SummaryOfNewFeaturesIn60. I didn't search for "Longest Common Subsequence," which would have foundLongestCommonSubsequence[], so thanks for the lesson :) – Reb.Cabin May 28 '12 at 20:20LongestCommonSubsequence, which is, in fact, a solution to Wikipedia's dijoint "longest common substring" problem. – Reb.Cabin May 29 '12 at 23:01