I implemented an algorithm using dictionaries with tuple keys, and the algorithm works, but it is very very slow. I have a set of strings. I was trying to implement an associative matrix where A["abc","bcde"]
= 2, the amount of overlap of the two strings. The tuples in L are keys in A. L is a sorted array => A[L[i]] < A[L[i+1]]
I merge the two strings with the biggest overlap in the set, then I update the "matrix" and the L list. I do it in a loop until the set has only 1 element. My problem is that with dictionary the algorithm is too slow. Is there a more efficient way to do this? Here is my code:
List<string> words = new List<string>(wordsFromFile);
Dictionary<Tuple<string, string>, int> A = new Dictionary<Tuple<string, string>, int>();
List<Tuple<string, string>> L = new List<Tuple<string,string>>();
(I used counting sort for making L. After that refreshing the matrix and the list is very time consuming:)
while (words.Count > 1)
{
string LastItem1 = L.Last().Item1;
string LastItem2 = L.Last().Item2;
words.Remove(LastItem1);
words.Remove(LastItem2);
string newElement = merge(LastItem1, LastItem2);
words.Add(newElement);
for (int i = 0; i < words.Count; ++i)
{
if (words[i] == newElement)
{
Tuple<string, string> tmp = new Tuple<string, string>(newElement, newElement);
A[tmp] = 0;
}
else
{
Tuple<string, string> tmp = new Tuple<string, string>(newElement, words[i]);
A[tmp] = A[new Tuple<string, string>(LastItem2, words[i])];
tmp = new Tuple<string, string>(words[i], newElement);
A[tmp] = A[new Tuple<string, string>(words[i], LastItem1)];
}
}
var itemsToRemove = A.Where(f => f.Key.Item1 == LastItem1 || f.Key.Item1 == LastItem2 || f.Key.Item2 == LastItem1 || f.Key.Item2 == LastItem2).ToArray();
foreach (var item in itemsToRemove)
A.Remove(item.Key);
L.Remove(L.Last());
for (int i = 0; i < L.Count(); ++i)
{
if (L[i].Item1 == LastItem2 && L[i].Item2 != LastItem1 && L[i].Item2 != newElement && L[i].Item2 != LastItem2) L[i] = new Tuple<string, string>(newElement, L[i].Item2);
else if (L[i].Item2 == LastItem1 && L[i].Item1 != LastItem1 && L[i].Item1 != newElement && L[i].Item1 != LastItem2) L[i] = new Tuple<string, string>(L[i].Item1, newElement);
}
var listitemsToRemove = L.Where(f => f.Item1 == LastItem1 || f.Item2 == LastItem2 || f.Item1 == LastItem2 || f.Item2 == LastItem1).ToArray();
foreach (var item in listitemsToRemove) L.Remove(item);
listitemsToRemove = L.Where(f => f.Item2 == LastItem2).ToArray();
}