mirror of
https://github.moeyy.xyz/https://github.com/trekhleb/javascript-algorithms.git
synced 2024-12-26 23:21:18 +08:00
Add LCS.
This commit is contained in:
parent
a672474acc
commit
9bef8de6b1
@ -44,7 +44,7 @@
|
|||||||
* [Knuth–Morris–Pratt Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/knuth-morris-pratt) - substring search
|
* [Knuth–Morris–Pratt Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/knuth-morris-pratt) - substring search
|
||||||
* [Rabin Karp Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/rabin-karp) - substring search
|
* [Rabin Karp Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/rabin-karp) - substring search
|
||||||
* [Longest Common Subsequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/longest-common-subsequnce) (LCS)
|
* [Longest Common Subsequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/longest-common-subsequnce) (LCS)
|
||||||
* longest common substring
|
* [Longest Common Substring](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/longest-common-substring)
|
||||||
* **Search**
|
* **Search**
|
||||||
* [Binary Search](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/search/binary-search)
|
* [Binary Search](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/search/binary-search)
|
||||||
* **Sorting**
|
* **Sorting**
|
||||||
@ -74,6 +74,7 @@
|
|||||||
* **Dynamic Programming**
|
* **Dynamic Programming**
|
||||||
* [Levenshtein Distance](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/levenshtein-distance) - minimum edit distance between two sequences
|
* [Levenshtein Distance](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/levenshtein-distance) - minimum edit distance between two sequences
|
||||||
* [Longest Common Subsequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/longest-common-subsequnce) (LCS)
|
* [Longest Common Subsequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/longest-common-subsequnce) (LCS)
|
||||||
|
* [Longest Common Substring](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/longest-common-substring)
|
||||||
* Increasing subsequence
|
* Increasing subsequence
|
||||||
* Knapsack problem
|
* Knapsack problem
|
||||||
* Maximum subarray
|
* Maximum subarray
|
||||||
|
24
src/algorithms/string/longest-common-substring/README.md
Normal file
24
src/algorithms/string/longest-common-substring/README.md
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# Longest Common Substring Problem
|
||||||
|
|
||||||
|
The longest common substring problem is to find the longest string
|
||||||
|
(or strings) that is a substring (or are substrings) of two or more
|
||||||
|
strings.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
The longest common substring of the strings `ABABC`, `BABCA` and
|
||||||
|
`ABCBA` is string `ABC` of length 3. Other common substrings are
|
||||||
|
`A`, `AB`, `B`, `BA`, `BC` and `C`.
|
||||||
|
|
||||||
|
```
|
||||||
|
ABABC
|
||||||
|
|||
|
||||||
|
BABCA
|
||||||
|
|||
|
||||||
|
ABCBA
|
||||||
|
```
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [Wikipedia](https://en.wikipedia.org/wiki/Longest_common_substring_problem)
|
||||||
|
- [YouTube](https://www.youtube.com/watch?v=BysNXJHzCEs)
|
@ -0,0 +1,11 @@
|
|||||||
|
import longestCommonSubstring from '../longestCommonSubstring';
|
||||||
|
|
||||||
|
describe('longestCommonSubstring', () => {
|
||||||
|
it('should find longest common substring between two strings', () => {
|
||||||
|
expect(longestCommonSubstring('', '')).toBe('');
|
||||||
|
expect(longestCommonSubstring('ABC', '')).toBe('');
|
||||||
|
expect(longestCommonSubstring('', 'ABC')).toBe('');
|
||||||
|
expect(longestCommonSubstring('ABABC', 'BABCA')).toBe('BABC');
|
||||||
|
expect(longestCommonSubstring('BABCA', 'ABCBA')).toBe('ABC');
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,59 @@
|
|||||||
|
/**
|
||||||
|
* @param {string} s1
|
||||||
|
* @param {string} s2
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
export default function longestCommonSubstring(s1, s2) {
|
||||||
|
// Init the matrix of all substring lengths to use Dynamic Programming approach.
|
||||||
|
const substringMatrix = Array(s2.length + 1).fill(null).map(() => {
|
||||||
|
return Array(s1.length + 1).fill(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Fill the first row and first column with zeros to provide initial values.
|
||||||
|
for (let columnIndex = 0; columnIndex <= s1.length; columnIndex += 1) {
|
||||||
|
substringMatrix[0][columnIndex] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let rowIndex = 0; rowIndex <= s2.length; rowIndex += 1) {
|
||||||
|
substringMatrix[rowIndex][0] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build the matrix of all substring lengths to use Dynamic Programming approach.
|
||||||
|
let longestSubstringLength = 0;
|
||||||
|
let longestSubstringColumn = 0;
|
||||||
|
let longestSubstringRow = 0;
|
||||||
|
|
||||||
|
for (let rowIndex = 1; rowIndex <= s2.length; rowIndex += 1) {
|
||||||
|
for (let columnIndex = 1; columnIndex <= s1.length; columnIndex += 1) {
|
||||||
|
if (s1[columnIndex - 1] === s2[rowIndex - 1]) {
|
||||||
|
substringMatrix[rowIndex][columnIndex] = substringMatrix[rowIndex - 1][columnIndex - 1] + 1;
|
||||||
|
} else {
|
||||||
|
substringMatrix[rowIndex][columnIndex] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to find the biggest length of all common substring lengths
|
||||||
|
// and to memorize its last character position (indices)
|
||||||
|
if (substringMatrix[rowIndex][columnIndex] > longestSubstringLength) {
|
||||||
|
longestSubstringLength = substringMatrix[rowIndex][columnIndex];
|
||||||
|
longestSubstringColumn = columnIndex;
|
||||||
|
longestSubstringRow = rowIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (longestSubstringLength === 0) {
|
||||||
|
// Longest common substring has not been found.
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detect the longest substring from the matrix.
|
||||||
|
let longestSubstring = '';
|
||||||
|
|
||||||
|
while (substringMatrix[longestSubstringRow][longestSubstringColumn] > 0) {
|
||||||
|
longestSubstring = s1[longestSubstringColumn - 1] + longestSubstring;
|
||||||
|
longestSubstringRow -= 1;
|
||||||
|
longestSubstringColumn -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return longestSubstring;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user