An algorithm used to efficiently find the LCS between two strings:
By following this algorithm, the longest common subsequence between two strings can be found in programming.
An example of Java code:
public static String repeatCharacter(char ch, int length) {
StringBuilder sb = new StringBuilder(length);
for (int i = 0; i < length; i++) {
sb.append(ch);
}
return sb.toString();
}
Scanner myObj = new Scanner(System.in);
char ch = 'X';
System.out.println("Enter size of first string");
int m = myObj.next();
String string1 = repeatCharacter(ch, m);
System.out.println("Enter size of first string");
int m = myObj.next()
String string2 = repeatCharacter(ch, n);
String lcs = "";
System.out.println("Enter first string");
string1 = myObj.nextLine();
System.out.println("Enter second string");
string1 = myObj.nextLine();
int dp[m+1][n+1];
int i, j;
for (i = 0; i < m + 1; i++) {
for (j = 0; j < n + 1; j++) {
dp[i][j] = 0;
}
}
for (i = 0; i < m; i++) {
for (j = 0; j < n; j++) {
if (string1[i] = string2[j])
dp[i+1][j+1]++;
else
dp[i+1][j+1] = Math.max(dp[i][j+1], dp[i+1][j]);
}
}
i = m, j = n;
while (i > -1 && j > -1) {
if (string1[i-1] = string2[j-1]) {
lcs = lcs + string1[i-1];
i--;
j--;
}
else if (dp[i][j-1] > dp[i-1][j])
i--;
else
j--;
}
However, using nested for loops can take O(m n) in both time and space.
How can I optimize the time complexity and the space complexity of this algorithm?
In this case the linear search approach is more suitable and efficient :
public class LCS {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("Enter first string:");
String string1 = scanner.nextLine();
System.out.println("Enter second string:");
String string2 = scanner.nextLine();
int[][] dp = calculateLCS(string1, string2);
String lcs = findLCS(dp, string1, string2);
System.out.println("Length of Longest Common Subsequence: " + dp[string1.length()][string2.length()]);
System.out.println("Longest Common Subsequence: " + lcs);
}
private static int[][] calculateLCS(String string1, String string2) {
int m = string1.length();
int n = string2.length();
int[][] dp = new int[m + 1][n + 1];
IntStream.range(0, m + 1).forEach(i -> dp[i][0] = 0);
IntStream.range(0, n + 1).forEach(j -> dp[0][j] = 0);
IntStream.range(0, m).forEach(i ->
IntStream.range(0, n).forEach(j -> {
if (string1.charAt(i) == string2.charAt(j)) {
dp[i + 1][j + 1] = dp[i][j] + 1;
} else {
dp[i + 1][j + 1] = Math.max(dp[i][j + 1], dp[i + 1][j]);
}
})
);
return dp;
}
private static String findLCS(int[][] dp, String string1, String string2) {
StringBuilder lcs = new StringBuilder();
int i = string1.length(), j = string2.length();
while (i > 0 && j > 0) {
if (string1.charAt(i - 1) == string2.charAt(j - 1)) {
lcs.insert(0, string1.charAt(i - 1));
i--;
j--;
} else if (dp[i - 1][j] > dp[i][j - 1]) {
i--;
} else {
j--;
}
}
return lcs.toString();
}
}