private IntList _longestCommonSubsequence(IList a, IList b)
{
int aStart = 0;
int aFinish = a.Count - 1;
IntList matchVector = new IntList();
Hashtable bMatches;
// initialize matchVector to length of a
for (int i = 0; i < a.Count; i++)
matchVector.Add(-1);
if (!IsPrepared(out bMatches))
{
int bStart = 0;
int bFinish = b.Count - 1;
// First we prune off any common elements at the beginning
while (aStart <= aFinish && bStart <= bFinish && compare(a[aStart], b[bStart]))
matchVector[aStart++] = bStart++;
// now the end
while (aStart <= aFinish && bStart <= bFinish && compare(a[aFinish], b[bFinish]))
matchVector[aFinish--] = bFinish--;
// Now compute the equivalence classes of positions of elements
bMatches =
_withPositionsOfInInterval(b, bStart, bFinish);
}
IntList thresh = new IntList();
TrioList links = new TrioList();
for (int i = aStart; i <= aFinish; i++)
{
IntList aimatches = (IntList) bMatches[a[i]];
if (aimatches != null)
{
int k = 0;
foreach (int j in aimatches)
{
// # optimization: most of the time this will be true
if (k > 0 && thresh[k] > j && thresh[k - 1] < j)
thresh[k] = j;
else
k = _replaceNextLargerWith(thresh, j, k);
// oddly, it's faster to always test this (CPU cache?).
if (k != -1)
{
Trio t = new Trio((Trio) (k > 0 ? links[k - 1] : null), i, j);
if (k == links.Count)
links.Add(t);
else
links[k] = t;
}
}
}
}
if (thresh.Count > 0)
{
for (Trio link = (Trio) links[thresh.Count - 1]; link != null; link = link.a)
matchVector[link.b] = link.c;
}
return matchVector;
}