I have a function for finding the longest matching substring in two string that is in need of some help. If you pass it two different strings, it will return the longest string fragment they have in common. I.e., if you had these two strings,

"This is a test string."
"What is a test object."

it would return " is a test ". Usually calls to it will be much more complex . A good baseline call would be a string with 2000 characters, and the same string with 10 arbitrary inserts and 10 arbitrary deletes. This takes an average of about 5 seconds on my machine. Currently, my code is spending about 99% percent of processing time in this function, so it's in obvious need of any optimizations I can come up with. I tried API functions to replace Mid$, but they were a bit slower--I also might try using byte arrays.

Here's the main function:
VB Code:
  1. Private Function SeekMatch(ByVal sOne As String, ByVal sTwo As String) As String
  2.  
  3.     'This function finds the longest substring of sTwo that exists in sOne, and returns it.  No matches
  4.     'returns a vbNullString.
  5.  
  6.     Dim sTest As String, lSize As Long, lStart As Long, lResult As Long, lLength As Long
  7.  
  8.     On Error GoTo ErrHand
  9.    
  10.     lLength = Len(sTwo)
  11.    
  12.     For lSize = lLength - 1 To 1 Step -1            'Loop through all posible substring lengths, descending.
  13.         For lStart = lLength - lSize To 1 Step -1   'Loop through all possible substring positions.
  14.             sTest = Mid$(sTwo, lStart, lSize)       'Get the substring from the Buffer string.
  15.             If InStrB(1, sOne, sTest) <> 0 Then     'If there is a match,
  16.                 SeekMatch = sTest                   'Return and exit.
  17.                 Exit Function
  18.             End If
  19.         Next lStart
  20.     Next lSize
  21.  
  22. ErrHand:
  23.     If Err.Number <> 0 Then                                
  24.         Call MsgBox("Error number " & Err.Number & vbCrLf & Err.Description & vbCrLf & _
  25.                     "in SeekMatch.", vbCritical)
  26.     End If
  27.    
  28. End Function
Here are a couple test functions I use to run benchmarks:
VB Code:
  1. Private Declare Function GetTickCount& Lib "kernel32" ()
  2.  
  3. Private Sub BenchMark()
  4.  
  5.     Dim sString1 As String, sString2 As String, lStart As Long, lEnd As Long, sOut As String
  6.    
  7.     sString1 = RandomString(2000)
  8.     sString2 = RandomChanges(sString1, 10, 10, 5)
  9.  
  10.     Debug.Print sString1
  11.     Debug.Print sString2
  12.    
  13.     lStart = GetTickCount
  14.     sOut = SeekMatch(sString1, sString2)
  15.     lEnd = GetTickCount
  16.  
  17.     Debug.Print sOut
  18.     Debug.Print lEnd - lStart
  19.    
  20. End Sub
  21.  
  22. Private Function RandomString(lChars As Long) As String
  23.  
  24.     Dim lCount As Long, bTemp() As Byte
  25.    
  26.     ReDim bTemp(lChars)
  27.     For lCount = LBound(bTemp) To UBound(bTemp)
  28.         bTemp(lCount) = Rand(33, 126)
  29.     Next lCount
  30.  
  31.     RandomString = StrConv(bTemp, vbUnicode)
  32.  
  33. End Function
  34.  
  35. Private Function RandomChanges(ByVal sString As String, lInserts As Long, lDeletes As Long, _
  36.                                Optional lBoundry As Long = 10) As String
  37.  
  38.     Dim lCount As Long, sOut As String, lStart As Long, lEnd As Long, sInsert As String, lLen As Long
  39.     Dim sLeft As String, sRight As String, lTemp As Long
  40.    
  41.     For lCount = 1 To lInserts
  42.         lLen = Len(sString)
  43.         lStart = Rand(1, lLen)
  44.         sInsert = RandomString(Rand(1, lBoundry))
  45.         If lStart = 0 Then
  46.             sString = sInsert & sString
  47.         ElseIf lStart = lLen Then
  48.             sString = sString & sInsert
  49.         Else
  50.             sLeft = Left$(sString, lStart)
  51.             sRight = Right$(sString, lLen - lStart)
  52.             sString = sLeft & sInsert & sRight
  53.         End If
  54.     Next lCount
  55.  
  56.     For lCount = 1 To lDeletes
  57.         lLen = Len(sString)
  58.         lStart = Rand(1, lLen)
  59.         If lStart + lBoundry > lLen Then
  60.             lEnd = lLen
  61.         Else
  62.             lEnd = Rand(lStart, lStart + lBoundry)
  63.         End If
  64.         If lStart = 1 And lEnd = lLen Then
  65.             sString = vbNullString
  66.             Exit For
  67.         End If
  68.         If lEnd = lLen Then
  69.             sString = Left$(sString, lStart - 1)
  70.         ElseIf lStart = 1 Then
  71.             sString = Right$(sString, lLen - lEnd)
  72.         Else
  73.             sLeft = Left$(sString, lStart - 1)
  74.             sRight = Right$(sString, lLen - lEnd)
  75.             sString = sLeft & sRight
  76.         End If
  77.     Next lCount
  78.  
  79.     RandomChanges = sString
  80.  
  81. End Function
  82.  
  83. Private Function Rand(lLow As Long, lHigh As Long) As Long
  84.  
  85.     Rand = Int((lHigh - lLow + 1) * Rnd + lLow)
  86.  
  87. End Function