To find the longest common subsequence (LCS) of two lines A and B, you can cross the two-dimensional array on the diagonal, as shown in the Link you send a message. Each element of the array corresponds to the problem of finding the LCS substrings A 'and B' (A, cut out by line number, B, cut out by its column number). This problem can be solved by calculating the values ββof all elements in the array. You must be sure that when calculating the value of the array element at all, the problem needed to calculate this value, it has been resolved. That's why you cross the two-dimensional array on the diagonal.
This solution can be scaled to find the longest common subsequence between the N rows, but this requires a general method iteration array of N measurements, so that each element is achieved only when all subtasks that element requires solutions have been solved.
Instead of repeating the N-dimensional array in a special order, you can also solve the problem recursively. When recursing, itβs important to preserve the intermediate solutions, as many industries will require the same intermediate solutions. I wrote a small example in C# , which makes it:
string lcs(string[] strings) { if (strings.Length == 0) return ""; if (strings.Length == 1) return strings[0]; int max = -1; int cacheSize = 1; for (int i = 0; i < strings.Length; i++) { cacheSize *= strings[i].Length; if (strings[i].Length > max) max = strings[i].Length; } string[] cache = new string[cacheSize]; int[] indexes = new int[strings.Length]; for (int i = 0; i < indexes.Length; i++) indexes[i] = strings[i].Length - 1; return lcsBack(strings, indexes, cache); } string lcsBack(string[] strings, int[] indexes, string[] cache) { for (int i = 0; i < indexes.Length; i++ ) if (indexes[i] == -1) return ""; bool match = true; for (int i = 1; i < indexes.Length; i++) { if (strings[0][indexes[0]] != strings[i][indexes[i]]) { match = false; break; } } if (match) { int[] newIndexes = new int[indexes.Length]; for (int i = 0; i < indexes.Length; i++) newIndexes[i] = indexes[i] - 1; string result = lcsBack(strings, newIndexes, cache) + strings[0][indexes[0]]; cache[calcCachePos(indexes, strings)] = result; return result; } else { string[] subStrings = new string[strings.Length]; for (int i = 0; i < strings.Length; i++) { if (indexes[i] <= 0) subStrings[i] = ""; else { int[] newIndexes = new int[indexes.Length]; for (int j = 0; j < indexes.Length; j++) newIndexes[j] = indexes[j]; newIndexes[i]--; int cachePos = calcCachePos(newIndexes, strings); if (cache[cachePos] == null) subStrings[i] = lcsBack(strings, newIndexes, cache); else subStrings[i] = cache[cachePos]; } } string longestString = ""; int longestLength = 0; for (int i = 0; i < subStrings.Length; i++) { if (subStrings[i].Length > longestLength) { longestString = subStrings[i]; longestLength = longestString.Length; } } cache[calcCachePos(indexes, strings)] = longestString; return longestString; } } int calcCachePos(int[] indexes, string[] strings) { int factor = 1; int pos = 0; for (int i = 0; i < indexes.Length; i++) { pos += indexes[i] * factor; factor *= strings[i].Length; } return pos; } cacheSize]; string lcs(string[] strings) { if (strings.Length == 0) return ""; if (strings.Length == 1) return strings[0]; int max = -1; int cacheSize = 1; for (int i = 0; i < strings.Length; i++) { cacheSize *= strings[i].Length; if (strings[i].Length > max) max = strings[i].Length; } string[] cache = new string[cacheSize]; int[] indexes = new int[strings.Length]; for (int i = 0; i < indexes.Length; i++) indexes[i] = strings[i].Length - 1; return lcsBack(strings, indexes, cache); } string lcsBack(string[] strings, int[] indexes, string[] cache) { for (int i = 0; i < indexes.Length; i++ ) if (indexes[i] == -1) return ""; bool match = true; for (int i = 1; i < indexes.Length; i++) { if (strings[0][indexes[0]] != strings[i][indexes[i]]) { match = false; break; } } if (match) { int[] newIndexes = new int[indexes.Length]; for (int i = 0; i < indexes.Length; i++) newIndexes[i] = indexes[i] - 1; string result = lcsBack(strings, newIndexes, cache) + strings[0][indexes[0]]; cache[calcCachePos(indexes, strings)] = result; return result; } else { string[] subStrings = new string[strings.Length]; for (int i = 0; i < strings.Length; i++) { if (indexes[i] <= 0) subStrings[i] = ""; else { int[] newIndexes = new int[indexes.Length]; for (int j = 0; j < indexes.Length; j++) newIndexes[j] = indexes[j]; newIndexes[i]--; int cachePos = calcCachePos(newIndexes, strings); if (cache[cachePos] == null) subStrings[i] = lcsBack(strings, newIndexes, cache); else subStrings[i] = cache[cachePos]; } } string longestString = ""; int longestLength = 0; for (int i = 0; i < subStrings.Length; i++) { if (subStrings[i].Length > longestLength) { longestString = subStrings[i]; longestLength = longestString.Length; } } cache[calcCachePos(indexes, strings)] = longestString; return longestString; } } int calcCachePos(int[] indexes, string[] strings) { int factor = 1; int pos = 0; for (int i = 0; i < indexes.Length; i++) { pos += indexes[i] * factor; factor *= strings[i].Length; } return pos; } ] .Length - string lcs(string[] strings) { if (strings.Length == 0) return ""; if (strings.Length == 1) return strings[0]; int max = -1; int cacheSize = 1; for (int i = 0; i < strings.Length; i++) { cacheSize *= strings[i].Length; if (strings[i].Length > max) max = strings[i].Length; } string[] cache = new string[cacheSize]; int[] indexes = new int[strings.Length]; for (int i = 0; i < indexes.Length; i++) indexes[i] = strings[i].Length - 1; return lcsBack(strings, indexes, cache); } string lcsBack(string[] strings, int[] indexes, string[] cache) { for (int i = 0; i < indexes.Length; i++ ) if (indexes[i] == -1) return ""; bool match = true; for (int i = 1; i < indexes.Length; i++) { if (strings[0][indexes[0]] != strings[i][indexes[i]]) { match = false; break; } } if (match) { int[] newIndexes = new int[indexes.Length]; for (int i = 0; i < indexes.Length; i++) newIndexes[i] = indexes[i] - 1; string result = lcsBack(strings, newIndexes, cache) + strings[0][indexes[0]]; cache[calcCachePos(indexes, strings)] = result; return result; } else { string[] subStrings = new string[strings.Length]; for (int i = 0; i < strings.Length; i++) { if (indexes[i] <= 0) subStrings[i] = ""; else { int[] newIndexes = new int[indexes.Length]; for (int j = 0; j < indexes.Length; j++) newIndexes[j] = indexes[j]; newIndexes[i]--; int cachePos = calcCachePos(newIndexes, strings); if (cache[cachePos] == null) subStrings[i] = lcsBack(strings, newIndexes, cache); else subStrings[i] = cache[cachePos]; } } string longestString = ""; int longestLength = 0; for (int i = 0; i < subStrings.Length; i++) { if (subStrings[i].Length > longestLength) { longestString = subStrings[i]; longestLength = longestString.Length; } } cache[calcCachePos(indexes, strings)] = longestString; return longestString; } } int calcCachePos(int[] indexes, string[] strings) { int factor = 1; int pos = 0; for (int i = 0; i < indexes.Length; i++) { pos += indexes[i] * factor; factor *= strings[i].Length; } return pos; } ); string lcs(string[] strings) { if (strings.Length == 0) return ""; if (strings.Length == 1) return strings[0]; int max = -1; int cacheSize = 1; for (int i = 0; i < strings.Length; i++) { cacheSize *= strings[i].Length; if (strings[i].Length > max) max = strings[i].Length; } string[] cache = new string[cacheSize]; int[] indexes = new int[strings.Length]; for (int i = 0; i < indexes.Length; i++) indexes[i] = strings[i].Length - 1; return lcsBack(strings, indexes, cache); } string lcsBack(string[] strings, int[] indexes, string[] cache) { for (int i = 0; i < indexes.Length; i++ ) if (indexes[i] == -1) return ""; bool match = true; for (int i = 1; i < indexes.Length; i++) { if (strings[0][indexes[0]] != strings[i][indexes[i]]) { match = false; break; } } if (match) { int[] newIndexes = new int[indexes.Length]; for (int i = 0; i < indexes.Length; i++) newIndexes[i] = indexes[i] - 1; string result = lcsBack(strings, newIndexes, cache) + strings[0][indexes[0]]; cache[calcCachePos(indexes, strings)] = result; return result; } else { string[] subStrings = new string[strings.Length]; for (int i = 0; i < strings.Length; i++) { if (indexes[i] <= 0) subStrings[i] = ""; else { int[] newIndexes = new int[indexes.Length]; for (int j = 0; j < indexes.Length; j++) newIndexes[j] = indexes[j]; newIndexes[i]--; int cachePos = calcCachePos(newIndexes, strings); if (cache[cachePos] == null) subStrings[i] = lcsBack(strings, newIndexes, cache); else subStrings[i] = cache[cachePos]; } } string longestString = ""; int longestLength = 0; for (int i = 0; i < subStrings.Length; i++) { if (subStrings[i].Length > longestLength) { longestString = subStrings[i]; longestLength = longestString.Length; } } cache[calcCachePos(indexes, strings)] = longestString; return longestString; } } int calcCachePos(int[] indexes, string[] strings) { int factor = 1; int pos = 0; for (int i = 0; i < indexes.Length; i++) { pos += indexes[i] * factor; factor *= strings[i].Length; } return pos; } int [] indexes, string [] cache) string lcs(string[] strings) { if (strings.Length == 0) return ""; if (strings.Length == 1) return strings[0]; int max = -1; int cacheSize = 1; for (int i = 0; i < strings.Length; i++) { cacheSize *= strings[i].Length; if (strings[i].Length > max) max = strings[i].Length; } string[] cache = new string[cacheSize]; int[] indexes = new int[strings.Length]; for (int i = 0; i < indexes.Length; i++) indexes[i] = strings[i].Length - 1; return lcsBack(strings, indexes, cache); } string lcsBack(string[] strings, int[] indexes, string[] cache) { for (int i = 0; i < indexes.Length; i++ ) if (indexes[i] == -1) return ""; bool match = true; for (int i = 1; i < indexes.Length; i++) { if (strings[0][indexes[0]] != strings[i][indexes[i]]) { match = false; break; } } if (match) { int[] newIndexes = new int[indexes.Length]; for (int i = 0; i < indexes.Length; i++) newIndexes[i] = indexes[i] - 1; string result = lcsBack(strings, newIndexes, cache) + strings[0][indexes[0]]; cache[calcCachePos(indexes, strings)] = result; return result; } else { string[] subStrings = new string[strings.Length]; for (int i = 0; i < strings.Length; i++) { if (indexes[i] <= 0) subStrings[i] = ""; else { int[] newIndexes = new int[indexes.Length]; for (int j = 0; j < indexes.Length; j++) newIndexes[j] = indexes[j]; newIndexes[i]--; int cachePos = calcCachePos(newIndexes, strings); if (cache[cachePos] == null) subStrings[i] = lcsBack(strings, newIndexes, cache); else subStrings[i] = cache[cachePos]; } } string longestString = ""; int longestLength = 0; for (int i = 0; i < subStrings.Length; i++) { if (subStrings[i].Length > longestLength) { longestString = subStrings[i]; longestLength = longestString.Length; } } cache[calcCachePos(indexes, strings)] = longestString; return longestString; } } int calcCachePos(int[] indexes, string[] strings) { int factor = 1; int pos = 0; for (int i = 0; i < indexes.Length; i++) { pos += indexes[i] * factor; factor *= strings[i].Length; } return pos; } [indexes [i]]) string lcs(string[] strings) { if (strings.Length == 0) return ""; if (strings.Length == 1) return strings[0]; int max = -1; int cacheSize = 1; for (int i = 0; i < strings.Length; i++) { cacheSize *= strings[i].Length; if (strings[i].Length > max) max = strings[i].Length; } string[] cache = new string[cacheSize]; int[] indexes = new int[strings.Length]; for (int i = 0; i < indexes.Length; i++) indexes[i] = strings[i].Length - 1; return lcsBack(strings, indexes, cache); } string lcsBack(string[] strings, int[] indexes, string[] cache) { for (int i = 0; i < indexes.Length; i++ ) if (indexes[i] == -1) return ""; bool match = true; for (int i = 1; i < indexes.Length; i++) { if (strings[0][indexes[0]] != strings[i][indexes[i]]) { match = false; break; } } if (match) { int[] newIndexes = new int[indexes.Length]; for (int i = 0; i < indexes.Length; i++) newIndexes[i] = indexes[i] - 1; string result = lcsBack(strings, newIndexes, cache) + strings[0][indexes[0]]; cache[calcCachePos(indexes, strings)] = result; return result; } else { string[] subStrings = new string[strings.Length]; for (int i = 0; i < strings.Length; i++) { if (indexes[i] <= 0) subStrings[i] = ""; else { int[] newIndexes = new int[indexes.Length]; for (int j = 0; j < indexes.Length; j++) newIndexes[j] = indexes[j]; newIndexes[i]--; int cachePos = calcCachePos(newIndexes, strings); if (cache[cachePos] == null) subStrings[i] = lcsBack(strings, newIndexes, cache); else subStrings[i] = cache[cachePos]; } } string longestString = ""; int longestLength = 0; for (int i = 0; i < subStrings.Length; i++) { if (subStrings[i].Length > longestLength) { longestString = subStrings[i]; longestLength = longestString.Length; } } cache[calcCachePos(indexes, strings)] = longestString; return longestString; } } int calcCachePos(int[] indexes, string[] strings) { int factor = 1; int pos = 0; for (int i = 0; i < indexes.Length; i++) { pos += indexes[i] * factor; factor *= strings[i].Length; } return pos; } indexes.Length]; string lcs(string[] strings) { if (strings.Length == 0) return ""; if (strings.Length == 1) return strings[0]; int max = -1; int cacheSize = 1; for (int i = 0; i < strings.Length; i++) { cacheSize *= strings[i].Length; if (strings[i].Length > max) max = strings[i].Length; } string[] cache = new string[cacheSize]; int[] indexes = new int[strings.Length]; for (int i = 0; i < indexes.Length; i++) indexes[i] = strings[i].Length - 1; return lcsBack(strings, indexes, cache); } string lcsBack(string[] strings, int[] indexes, string[] cache) { for (int i = 0; i < indexes.Length; i++ ) if (indexes[i] == -1) return ""; bool match = true; for (int i = 1; i < indexes.Length; i++) { if (strings[0][indexes[0]] != strings[i][indexes[i]]) { match = false; break; } } if (match) { int[] newIndexes = new int[indexes.Length]; for (int i = 0; i < indexes.Length; i++) newIndexes[i] = indexes[i] - 1; string result = lcsBack(strings, newIndexes, cache) + strings[0][indexes[0]]; cache[calcCachePos(indexes, strings)] = result; return result; } else { string[] subStrings = new string[strings.Length]; for (int i = 0; i < strings.Length; i++) { if (indexes[i] <= 0) subStrings[i] = ""; else { int[] newIndexes = new int[indexes.Length]; for (int j = 0; j < indexes.Length; j++) newIndexes[j] = indexes[j]; newIndexes[i]--; int cachePos = calcCachePos(newIndexes, strings); if (cache[cachePos] == null) subStrings[i] = lcsBack(strings, newIndexes, cache); else subStrings[i] = cache[cachePos]; } } string longestString = ""; int longestLength = 0; for (int i = 0; i < subStrings.Length; i++) { if (subStrings[i].Length > longestLength) { longestString = subStrings[i]; longestLength = longestString.Length; } } cache[calcCachePos(indexes, strings)] = longestString; return longestString; } } int calcCachePos(int[] indexes, string[] strings) { int factor = 1; int pos = 0; for (int i = 0; i < indexes.Length; i++) { pos += indexes[i] * factor; factor *= strings[i].Length; } return pos; } , cache) + strings [ string lcs(string[] strings) { if (strings.Length == 0) return ""; if (strings.Length == 1) return strings[0]; int max = -1; int cacheSize = 1; for (int i = 0; i < strings.Length; i++) { cacheSize *= strings[i].Length; if (strings[i].Length > max) max = strings[i].Length; } string[] cache = new string[cacheSize]; int[] indexes = new int[strings.Length]; for (int i = 0; i < indexes.Length; i++) indexes[i] = strings[i].Length - 1; return lcsBack(strings, indexes, cache); } string lcsBack(string[] strings, int[] indexes, string[] cache) { for (int i = 0; i < indexes.Length; i++ ) if (indexes[i] == -1) return ""; bool match = true; for (int i = 1; i < indexes.Length; i++) { if (strings[0][indexes[0]] != strings[i][indexes[i]]) { match = false; break; } } if (match) { int[] newIndexes = new int[indexes.Length]; for (int i = 0; i < indexes.Length; i++) newIndexes[i] = indexes[i] - 1; string result = lcsBack(strings, newIndexes, cache) + strings[0][indexes[0]]; cache[calcCachePos(indexes, strings)] = result; return result; } else { string[] subStrings = new string[strings.Length]; for (int i = 0; i < strings.Length; i++) { if (indexes[i] <= 0) subStrings[i] = ""; else { int[] newIndexes = new int[indexes.Length]; for (int j = 0; j < indexes.Length; j++) newIndexes[j] = indexes[j]; newIndexes[i]--; int cachePos = calcCachePos(newIndexes, strings); if (cache[cachePos] == null) subStrings[i] = lcsBack(strings, newIndexes, cache); else subStrings[i] = cache[cachePos]; } } string longestString = ""; int longestLength = 0; for (int i = 0; i < subStrings.Length; i++) { if (subStrings[i].Length > longestLength) { longestString = subStrings[i]; longestLength = longestString.Length; } } cache[calcCachePos(indexes, strings)] = longestString; return longestString; } } int calcCachePos(int[] indexes, string[] strings) { int factor = 1; int pos = 0; for (int i = 0; i < indexes.Length; i++) { pos += indexes[i] * factor; factor *= strings[i].Length; } return pos; } ] = result; string lcs(string[] strings) { if (strings.Length == 0) return ""; if (strings.Length == 1) return strings[0]; int max = -1; int cacheSize = 1; for (int i = 0; i < strings.Length; i++) { cacheSize *= strings[i].Length; if (strings[i].Length > max) max = strings[i].Length; } string[] cache = new string[cacheSize]; int[] indexes = new int[strings.Length]; for (int i = 0; i < indexes.Length; i++) indexes[i] = strings[i].Length - 1; return lcsBack(strings, indexes, cache); } string lcsBack(string[] strings, int[] indexes, string[] cache) { for (int i = 0; i < indexes.Length; i++ ) if (indexes[i] == -1) return ""; bool match = true; for (int i = 1; i < indexes.Length; i++) { if (strings[0][indexes[0]] != strings[i][indexes[i]]) { match = false; break; } } if (match) { int[] newIndexes = new int[indexes.Length]; for (int i = 0; i < indexes.Length; i++) newIndexes[i] = indexes[i] - 1; string result = lcsBack(strings, newIndexes, cache) + strings[0][indexes[0]]; cache[calcCachePos(indexes, strings)] = result; return result; } else { string[] subStrings = new string[strings.Length]; for (int i = 0; i < strings.Length; i++) { if (indexes[i] <= 0) subStrings[i] = ""; else { int[] newIndexes = new int[indexes.Length]; for (int j = 0; j < indexes.Length; j++) newIndexes[j] = indexes[j]; newIndexes[i]--; int cachePos = calcCachePos(newIndexes, strings); if (cache[cachePos] == null) subStrings[i] = lcsBack(strings, newIndexes, cache); else subStrings[i] = cache[cachePos]; } } string longestString = ""; int longestLength = 0; for (int i = 0; i < subStrings.Length; i++) { if (subStrings[i].Length > longestLength) { longestString = subStrings[i]; longestLength = longestString.Length; } } cache[calcCachePos(indexes, strings)] = longestString; return longestString; } } int calcCachePos(int[] indexes, string[] strings) { int factor = 1; int pos = 0; for (int i = 0; i < indexes.Length; i++) { pos += indexes[i] * factor; factor *= strings[i].Length; } return pos; } strings.Length]; string lcs(string[] strings) { if (strings.Length == 0) return ""; if (strings.Length == 1) return strings[0]; int max = -1; int cacheSize = 1; for (int i = 0; i < strings.Length; i++) { cacheSize *= strings[i].Length; if (strings[i].Length > max) max = strings[i].Length; } string[] cache = new string[cacheSize]; int[] indexes = new int[strings.Length]; for (int i = 0; i < indexes.Length; i++) indexes[i] = strings[i].Length - 1; return lcsBack(strings, indexes, cache); } string lcsBack(string[] strings, int[] indexes, string[] cache) { for (int i = 0; i < indexes.Length; i++ ) if (indexes[i] == -1) return ""; bool match = true; for (int i = 1; i < indexes.Length; i++) { if (strings[0][indexes[0]] != strings[i][indexes[i]]) { match = false; break; } } if (match) { int[] newIndexes = new int[indexes.Length]; for (int i = 0; i < indexes.Length; i++) newIndexes[i] = indexes[i] - 1; string result = lcsBack(strings, newIndexes, cache) + strings[0][indexes[0]]; cache[calcCachePos(indexes, strings)] = result; return result; } else { string[] subStrings = new string[strings.Length]; for (int i = 0; i < strings.Length; i++) { if (indexes[i] <= 0) subStrings[i] = ""; else { int[] newIndexes = new int[indexes.Length]; for (int j = 0; j < indexes.Length; j++) newIndexes[j] = indexes[j]; newIndexes[i]--; int cachePos = calcCachePos(newIndexes, strings); if (cache[cachePos] == null) subStrings[i] = lcsBack(strings, newIndexes, cache); else subStrings[i] = cache[cachePos]; } } string longestString = ""; int longestLength = 0; for (int i = 0; i < subStrings.Length; i++) { if (subStrings[i].Length > longestLength) { longestString = subStrings[i]; longestLength = longestString.Length; } } cache[calcCachePos(indexes, strings)] = longestString; return longestString; } } int calcCachePos(int[] indexes, string[] strings) { int factor = 1; int pos = 0; for (int i = 0; i < indexes.Length; i++) { pos += indexes[i] * factor; factor *= strings[i].Length; } return pos; } indexes.Length]; string lcs(string[] strings) { if (strings.Length == 0) return ""; if (strings.Length == 1) return strings[0]; int max = -1; int cacheSize = 1; for (int i = 0; i < strings.Length; i++) { cacheSize *= strings[i].Length; if (strings[i].Length > max) max = strings[i].Length; } string[] cache = new string[cacheSize]; int[] indexes = new int[strings.Length]; for (int i = 0; i < indexes.Length; i++) indexes[i] = strings[i].Length - 1; return lcsBack(strings, indexes, cache); } string lcsBack(string[] strings, int[] indexes, string[] cache) { for (int i = 0; i < indexes.Length; i++ ) if (indexes[i] == -1) return ""; bool match = true; for (int i = 1; i < indexes.Length; i++) { if (strings[0][indexes[0]] != strings[i][indexes[i]]) { match = false; break; } } if (match) { int[] newIndexes = new int[indexes.Length]; for (int i = 0; i < indexes.Length; i++) newIndexes[i] = indexes[i] - 1; string result = lcsBack(strings, newIndexes, cache) + strings[0][indexes[0]]; cache[calcCachePos(indexes, strings)] = result; return result; } else { string[] subStrings = new string[strings.Length]; for (int i = 0; i < strings.Length; i++) { if (indexes[i] <= 0) subStrings[i] = ""; else { int[] newIndexes = new int[indexes.Length]; for (int j = 0; j < indexes.Length; j++) newIndexes[j] = indexes[j]; newIndexes[i]--; int cachePos = calcCachePos(newIndexes, strings); if (cache[cachePos] == null) subStrings[i] = lcsBack(strings, newIndexes, cache); else subStrings[i] = cache[cachePos]; } } string longestString = ""; int longestLength = 0; for (int i = 0; i < subStrings.Length; i++) { if (subStrings[i].Length > longestLength) { longestString = subStrings[i]; longestLength = longestString.Length; } } cache[calcCachePos(indexes, strings)] = longestString; return longestString; } } int calcCachePos(int[] indexes, string[] strings) { int factor = 1; int pos = 0; for (int i = 0; i < indexes.Length; i++) { pos += indexes[i] * factor; factor *= strings[i].Length; } return pos; } ); string lcs(string[] strings) { if (strings.Length == 0) return ""; if (strings.Length == 1) return strings[0]; int max = -1; int cacheSize = 1; for (int i = 0; i < strings.Length; i++) { cacheSize *= strings[i].Length; if (strings[i].Length > max) max = strings[i].Length; } string[] cache = new string[cacheSize]; int[] indexes = new int[strings.Length]; for (int i = 0; i < indexes.Length; i++) indexes[i] = strings[i].Length - 1; return lcsBack(strings, indexes, cache); } string lcsBack(string[] strings, int[] indexes, string[] cache) { for (int i = 0; i < indexes.Length; i++ ) if (indexes[i] == -1) return ""; bool match = true; for (int i = 1; i < indexes.Length; i++) { if (strings[0][indexes[0]] != strings[i][indexes[i]]) { match = false; break; } } if (match) { int[] newIndexes = new int[indexes.Length]; for (int i = 0; i < indexes.Length; i++) newIndexes[i] = indexes[i] - 1; string result = lcsBack(strings, newIndexes, cache) + strings[0][indexes[0]]; cache[calcCachePos(indexes, strings)] = result; return result; } else { string[] subStrings = new string[strings.Length]; for (int i = 0; i < strings.Length; i++) { if (indexes[i] <= 0) subStrings[i] = ""; else { int[] newIndexes = new int[indexes.Length]; for (int j = 0; j < indexes.Length; j++) newIndexes[j] = indexes[j]; newIndexes[i]--; int cachePos = calcCachePos(newIndexes, strings); if (cache[cachePos] == null) subStrings[i] = lcsBack(strings, newIndexes, cache); else subStrings[i] = cache[cachePos]; } } string longestString = ""; int longestLength = 0; for (int i = 0; i < subStrings.Length; i++) { if (subStrings[i].Length > longestLength) { longestString = subStrings[i]; longestLength = longestString.Length; } } cache[calcCachePos(indexes, strings)] = longestString; return longestString; } } int calcCachePos(int[] indexes, string[] strings) { int factor = 1; int pos = 0; for (int i = 0; i < indexes.Length; i++) { pos += indexes[i] * factor; factor *= strings[i].Length; } return pos; } longestLength) string lcs(string[] strings) { if (strings.Length == 0) return ""; if (strings.Length == 1) return strings[0]; int max = -1; int cacheSize = 1; for (int i = 0; i < strings.Length; i++) { cacheSize *= strings[i].Length; if (strings[i].Length > max) max = strings[i].Length; } string[] cache = new string[cacheSize]; int[] indexes = new int[strings.Length]; for (int i = 0; i < indexes.Length; i++) indexes[i] = strings[i].Length - 1; return lcsBack(strings, indexes, cache); } string lcsBack(string[] strings, int[] indexes, string[] cache) { for (int i = 0; i < indexes.Length; i++ ) if (indexes[i] == -1) return ""; bool match = true; for (int i = 1; i < indexes.Length; i++) { if (strings[0][indexes[0]] != strings[i][indexes[i]]) { match = false; break; } } if (match) { int[] newIndexes = new int[indexes.Length]; for (int i = 0; i < indexes.Length; i++) newIndexes[i] = indexes[i] - 1; string result = lcsBack(strings, newIndexes, cache) + strings[0][indexes[0]]; cache[calcCachePos(indexes, strings)] = result; return result; } else { string[] subStrings = new string[strings.Length]; for (int i = 0; i < strings.Length; i++) { if (indexes[i] <= 0) subStrings[i] = ""; else { int[] newIndexes = new int[indexes.Length]; for (int j = 0; j < indexes.Length; j++) newIndexes[j] = indexes[j]; newIndexes[i]--; int cachePos = calcCachePos(newIndexes, strings); if (cache[cachePos] == null) subStrings[i] = lcsBack(strings, newIndexes, cache); else subStrings[i] = cache[cachePos]; } } string longestString = ""; int longestLength = 0; for (int i = 0; i < subStrings.Length; i++) { if (subStrings[i].Length > longestLength) { longestString = subStrings[i]; longestLength = longestString.Length; } } cache[calcCachePos(indexes, strings)] = longestString; return longestString; } } int calcCachePos(int[] indexes, string[] strings) { int factor = 1; int pos = 0; for (int i = 0; i < indexes.Length; i++) { pos += indexes[i] * factor; factor *= strings[i].Length; } return pos; } ] = longestString; string lcs(string[] strings) { if (strings.Length == 0) return ""; if (strings.Length == 1) return strings[0]; int max = -1; int cacheSize = 1; for (int i = 0; i < strings.Length; i++) { cacheSize *= strings[i].Length; if (strings[i].Length > max) max = strings[i].Length; } string[] cache = new string[cacheSize]; int[] indexes = new int[strings.Length]; for (int i = 0; i < indexes.Length; i++) indexes[i] = strings[i].Length - 1; return lcsBack(strings, indexes, cache); } string lcsBack(string[] strings, int[] indexes, string[] cache) { for (int i = 0; i < indexes.Length; i++ ) if (indexes[i] == -1) return ""; bool match = true; for (int i = 1; i < indexes.Length; i++) { if (strings[0][indexes[0]] != strings[i][indexes[i]]) { match = false; break; } } if (match) { int[] newIndexes = new int[indexes.Length]; for (int i = 0; i < indexes.Length; i++) newIndexes[i] = indexes[i] - 1; string result = lcsBack(strings, newIndexes, cache) + strings[0][indexes[0]]; cache[calcCachePos(indexes, strings)] = result; return result; } else { string[] subStrings = new string[strings.Length]; for (int i = 0; i < strings.Length; i++) { if (indexes[i] <= 0) subStrings[i] = ""; else { int[] newIndexes = new int[indexes.Length]; for (int j = 0; j < indexes.Length; j++) newIndexes[j] = indexes[j]; newIndexes[i]--; int cachePos = calcCachePos(newIndexes, strings); if (cache[cachePos] == null) subStrings[i] = lcsBack(strings, newIndexes, cache); else subStrings[i] = cache[cachePos]; } } string longestString = ""; int longestLength = 0; for (int i = 0; i < subStrings.Length; i++) { if (subStrings[i].Length > longestLength) { longestString = subStrings[i]; longestLength = longestString.Length; } } cache[calcCachePos(indexes, strings)] = longestString; return longestString; } } int calcCachePos(int[] indexes, string[] strings) { int factor = 1; int pos = 0; for (int i = 0; i < indexes.Length; i++) { pos += indexes[i] * factor; factor *= strings[i].Length; } return pos; } string [] strings) string lcs(string[] strings) { if (strings.Length == 0) return ""; if (strings.Length == 1) return strings[0]; int max = -1; int cacheSize = 1; for (int i = 0; i < strings.Length; i++) { cacheSize *= strings[i].Length; if (strings[i].Length > max) max = strings[i].Length; } string[] cache = new string[cacheSize]; int[] indexes = new int[strings.Length]; for (int i = 0; i < indexes.Length; i++) indexes[i] = strings[i].Length - 1; return lcsBack(strings, indexes, cache); } string lcsBack(string[] strings, int[] indexes, string[] cache) { for (int i = 0; i < indexes.Length; i++ ) if (indexes[i] == -1) return ""; bool match = true; for (int i = 1; i < indexes.Length; i++) { if (strings[0][indexes[0]] != strings[i][indexes[i]]) { match = false; break; } } if (match) { int[] newIndexes = new int[indexes.Length]; for (int i = 0; i < indexes.Length; i++) newIndexes[i] = indexes[i] - 1; string result = lcsBack(strings, newIndexes, cache) + strings[0][indexes[0]]; cache[calcCachePos(indexes, strings)] = result; return result; } else { string[] subStrings = new string[strings.Length]; for (int i = 0; i < strings.Length; i++) { if (indexes[i] <= 0) subStrings[i] = ""; else { int[] newIndexes = new int[indexes.Length]; for (int j = 0; j < indexes.Length; j++) newIndexes[j] = indexes[j]; newIndexes[i]--; int cachePos = calcCachePos(newIndexes, strings); if (cache[cachePos] == null) subStrings[i] = lcsBack(strings, newIndexes, cache); else subStrings[i] = cache[cachePos]; } } string longestString = ""; int longestLength = 0; for (int i = 0; i < subStrings.Length; i++) { if (subStrings[i].Length > longestLength) { longestString = subStrings[i]; longestLength = longestString.Length; } } cache[calcCachePos(indexes, strings)] = longestString; return longestString; } } int calcCachePos(int[] indexes, string[] strings) { int factor = 1; int pos = 0; for (int i = 0; i < indexes.Length; i++) { pos += indexes[i] * factor; factor *= strings[i].Length; } return pos; }
My sample code can be optimized further. Many of rows cached - it duplicates, and some duplicate with the addition of only one added symbol. It takes up more space than is needed when the input lines are great.
At the entrance: "666222054263314443712", "5432127413542377777", "6664664565464057425"
Return the LCS: "54442"