X Tutup
Skip to content

Commit db369fc

Browse files
committed
Freestyle | The Longest Common Subsequence (LCS) | Java
1 parent 6bf8ab7 commit db369fc

File tree

3 files changed

+138
-0
lines changed

3 files changed

+138
-0
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Longest Common Subsequence with Skips
2+
3+
## Problem Statement
4+
5+
Given two strings `text1` and `text2`, and an integer `k`, return the length of the **longest common subsequence** you
6+
can form **by skipping at most `k` characters in either string**. At any point, you may skip a character in `text1` or
7+
`text2` (but not both at the same time), and you can do this up to `k` times total.
8+
9+
A subsequence of a string is a new string generated from the original string with some characters (possibly none)
10+
deleted without changing the relative order of the remaining characters.
11+
12+
## Input
13+
14+
- A string `text1` of length `n` (`1 <= n <= 1000`)
15+
- A string `text2` of length `m` (`1 <= m <= 1000`)
16+
- An integer `k` (`0 <= k <= min(n, m)`)
17+
18+
## Output
19+
20+
- An integer representing the length of the longest common subsequence obtainable by skipping at most `k` characters in
21+
either `text1` or `text2`
22+
23+
## Example
24+
25+
### Input
26+
27+
`text1 = "abcde"`
28+
`text2 = "acebd"`
29+
`k = 1`
30+
31+
### Output
32+
3
33+
34+
### Explanation
35+
36+
The standard LCS is `"acd"` (length 3).
37+
By skipping `'b'` from `text2`, we can align more characters and obtain the subsequence `"acd"` (length 3).
38+
39+
## Constraints
40+
41+
- `1 <= text1.length, text2.length <= 1000`
42+
- `0 <= k <= min(text1.length, text2.length)`
43+
- `text1` and `text2` consist of lowercase English letters only.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.devstromo.dp.lcs.practice.with_k_skips;
2+
3+
public class Solution {
4+
public int longestCommonSubsequenceWithSkips(String text1, String text2, int k) {
5+
int n = text1.length();
6+
int m = text2.length();
7+
int[][][] dp = new int[n + 1][m + 1][k + 1];
8+
9+
for (int i = 0; i <= n; i++) {
10+
for (int j = 0; j <= m; j++) {
11+
for (int l = 0; l <= k; l++) {
12+
if (i == 0 || j == 0) {
13+
dp[i][j][l] = 0;
14+
continue;
15+
}
16+
if (text1.charAt(i - 1) == text2.charAt(j - 1)) {
17+
dp[i][j][l] = dp[i - 1][j - 1][l] + 1;
18+
} else {
19+
int skipText1 = (l > 0) ? dp[i - 1][j][l - 1] : 0;
20+
int skipText2 = (l > 0) ? dp[i][j - 1][l - 1] : 0;
21+
dp[i][j][l] = Math.max(dp[i - 1][j][l], dp[i][j - 1][l]);
22+
if (l > 0) {
23+
dp[i][j][l] = Math.max(dp[i][j][l], Math.max(skipText1, skipText2));
24+
}
25+
}
26+
}
27+
}
28+
}
29+
30+
int maxLCS = 0;
31+
for (int l = 0; l <= k; l++) {
32+
maxLCS = Math.max(maxLCS, dp[n][m][l]);
33+
}
34+
return maxLCS;
35+
}
36+
37+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package com.devstromo.dp.lcs.practice.with_k_skips;
2+
3+
import org.junit.jupiter.api.Test;
4+
5+
import static org.junit.jupiter.api.Assertions.*;
6+
7+
class SolutionUnitTest {
8+
private final Solution solver = new Solution();
9+
10+
@Test
11+
void basicTest() {
12+
String text1 = "abcde";
13+
String text2 = "acebd";
14+
int k = 1;
15+
assertEquals(3, solver.longestCommonSubsequenceWithSkips(text1, text2, k));
16+
}
17+
18+
@Test
19+
void testNoSkipsSameAsLCS() {
20+
String text1 = "abc";
21+
String text2 = "abc";
22+
int k = 0;
23+
assertEquals(3, solver.longestCommonSubsequenceWithSkips(text1, text2, k));
24+
}
25+
26+
@Test
27+
void testWithSkipsImprovesLCS() {
28+
String text1 = "abcxyz";
29+
String text2 = "axyz";
30+
int k = 1;
31+
assertEquals(4, solver.longestCommonSubsequenceWithSkips(text1, text2, k));
32+
}
33+
34+
@Test
35+
void testEmptyString() {
36+
String text1 = "";
37+
String text2 = "abc";
38+
int k = 2;
39+
assertEquals(0, solver.longestCommonSubsequenceWithSkips(text1, text2, k));
40+
}
41+
42+
@Test
43+
void testSkipsUnused() {
44+
String text1 = "abcdef";
45+
String text2 = "acef";
46+
int k = 3;
47+
assertEquals(4, solver.longestCommonSubsequenceWithSkips(text1, text2, k));
48+
}
49+
50+
@Test
51+
void testAllSkipsNeeded() {
52+
String text1 = "abc";
53+
String text2 = "xyz";
54+
int k = 3;
55+
assertEquals(0, solver.longestCommonSubsequenceWithSkips(text1, text2, k));
56+
}
57+
58+
}

0 commit comments

Comments
 (0)
X Tutup