The longest common subsequence for a number of rows

For the longest common subsequence of the 2 lines I found many examples on the Internet, and I believe that I understand the decision.
I do not understand what is the right way to apply this problem for the rows N ? Is the same decision somehow applied? How? Is the solution is different? What?

+4
source share
2 answers

This problem is NP-hard , when the input has an arbitrary number of rows. This problem becomes available only when the input is a fixed number of rows. If the input is k lines, we can apply the same method of the DP, using a k-dimensional array to store the optimal solutions of subtasks.

Link: The longest common subsequence problem

+4
source

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"

+1
source

All Articles