From 1bf0fe05a2284c971825b466d92a493c6b62829d Mon Sep 17 00:00:00 2001 From: mmessmer Date: Fri, 9 Oct 2020 10:53:39 +0200 Subject: [PATCH 1/4] LPS algorithm --- .../LongestPalindromicSubsequence.java | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 DynamicProgramming/LongestPalindromicSubsequence.java diff --git a/DynamicProgramming/LongestPalindromicSubsequence.java b/DynamicProgramming/LongestPalindromicSubsequence.java new file mode 100644 index 000000000..2ad1c0255 --- /dev/null +++ b/DynamicProgramming/LongestPalindromicSubsequence.java @@ -0,0 +1,58 @@ +package DynamicProgramming; +import java.lang.*; +import java.io.*; +import java.util.*; + +/** + * @author Matteo Messmer https://github.com/matteomessmer + */ +public class LongestPalindromicSubsequence { + public static void main(String[] args) { + String a = "BBABCBCAB"; + String b = "BABCBAB"; + + String aLPS = LPS(a); + String bLPS = LPS(b); + + System.out.println(a + " => " + aLPS); + System.out.println(b + " => " + bLPS); + } + + private static String LPS(String original) { + StringBuilder reverse = new StringBuilder(); + reverse.append(original); + reverse = reverse.reverse(); + return recursiveLPS(original, reverse); + } + + private static String recursiveLPS(String original, String reverse) { + String bestResult = "" + + //no more chars, then return empty + if(original.length() == 0 || reverse.length() == 0) { + bestResult = ""; + } else { + + //if the last chars match, then remove it from both strings and recur + if(original.charAt(original.length() - 1) == reverse.charAt(reverse.length() - 1)) { + String bestSubResult = recursiveLPS(original.substring(0, original.length() - 1), reverse.substring(0, reverse.length() - 1)); + + bestResult = reverse.charAt(reverse.length() - 1) + bestSubResult; + } else { + //otherwise (1) ignore the last character of reverse, and recur on original and updated reverse again + //(2) ignore the last character of original and recur on the updated original and reverse again + //then select the best result from these two subproblems. + + String bestSubResult1 = recursiveLPS(original, reverse.substring(0, reverse.length() - 1)); + String bestSubResult2 = recursiveLPS(original.substring(0, original.length() - 1), reverse); + if(bestSubResult1.length()>bestSubResult2.length()) { + bestResult = bestSubResult1; + } else { + bestResult = bestSubResult2; + } + } + } + + return bestResult; + } +} \ No newline at end of file From 196fcb30df4b5a3304b16858a7c5f598ce3bf173 Mon Sep 17 00:00:00 2001 From: mmessmer Date: Fri, 9 Oct 2020 10:59:20 +0200 Subject: [PATCH 2/4] LPS algorithm fix --- DynamicProgramming/LongestPalindromicSubsequence.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DynamicProgramming/LongestPalindromicSubsequence.java b/DynamicProgramming/LongestPalindromicSubsequence.java index 2ad1c0255..4f017fe10 100644 --- a/DynamicProgramming/LongestPalindromicSubsequence.java +++ b/DynamicProgramming/LongestPalindromicSubsequence.java @@ -22,11 +22,11 @@ public class LongestPalindromicSubsequence { StringBuilder reverse = new StringBuilder(); reverse.append(original); reverse = reverse.reverse(); - return recursiveLPS(original, reverse); + return recursiveLPS(original, reverse.toString()); } private static String recursiveLPS(String original, String reverse) { - String bestResult = "" + String bestResult = ""; //no more chars, then return empty if(original.length() == 0 || reverse.length() == 0) { From 9bcb7f5f0b706ebcd45f8cb77611d0b4b3a6eb51 Mon Sep 17 00:00:00 2001 From: mmessmer Date: Fri, 9 Oct 2020 11:42:53 +0200 Subject: [PATCH 3/4] Fixes: #1709 --- DynamicProgramming/LongestPalindromicSubsequence.java | 1 + 1 file changed, 1 insertion(+) diff --git a/DynamicProgramming/LongestPalindromicSubsequence.java b/DynamicProgramming/LongestPalindromicSubsequence.java index 4f017fe10..28b43a5fe 100644 --- a/DynamicProgramming/LongestPalindromicSubsequence.java +++ b/DynamicProgramming/LongestPalindromicSubsequence.java @@ -5,6 +5,7 @@ import java.util.*; /** * @author Matteo Messmer https://github.com/matteomessmer + * Algorithm explanation https://www.educative.io/edpresso/longest-palindromic-subsequence-algorithm */ public class LongestPalindromicSubsequence { public static void main(String[] args) { From 60c0291e6a18ccdd8f0d1b1b54aa3f55d768f90b Mon Sep 17 00:00:00 2001 From: mmessmer Date: Sat, 10 Oct 2020 18:07:03 +0200 Subject: [PATCH 4/4] added tests --- .../LongestPalindromicSubsequence.java | 8 ++--- .../LongestPalindromicSubsequenceTests.java | 33 +++++++++++++++++++ 2 files changed, 36 insertions(+), 5 deletions(-) create mode 100644 DynamicProgramming/LongestPalindromicSubsequenceTests.java diff --git a/DynamicProgramming/LongestPalindromicSubsequence.java b/DynamicProgramming/LongestPalindromicSubsequence.java index 28b43a5fe..53ea6a794 100644 --- a/DynamicProgramming/LongestPalindromicSubsequence.java +++ b/DynamicProgramming/LongestPalindromicSubsequence.java @@ -1,10 +1,9 @@ -package DynamicProgramming; +package test; import java.lang.*; import java.io.*; import java.util.*; /** - * @author Matteo Messmer https://github.com/matteomessmer * Algorithm explanation https://www.educative.io/edpresso/longest-palindromic-subsequence-algorithm */ public class LongestPalindromicSubsequence { @@ -19,9 +18,8 @@ public class LongestPalindromicSubsequence { System.out.println(b + " => " + bLPS); } - private static String LPS(String original) { - StringBuilder reverse = new StringBuilder(); - reverse.append(original); + public static String LPS(String original) throws IllegalArgumentException { + StringBuilder reverse = new StringBuilder(original); reverse = reverse.reverse(); return recursiveLPS(original, reverse.toString()); } diff --git a/DynamicProgramming/LongestPalindromicSubsequenceTests.java b/DynamicProgramming/LongestPalindromicSubsequenceTests.java new file mode 100644 index 000000000..7171f4849 --- /dev/null +++ b/DynamicProgramming/LongestPalindromicSubsequenceTests.java @@ -0,0 +1,33 @@ +package test; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.Test; + +class LongestPalindromicSubsequenceTests { + + @Test + void test1() { + assertEquals(LongestPalindromicSubsequence.LPS(""), ""); + } + + @Test + void test2() { + assertEquals(LongestPalindromicSubsequence.LPS("A"), "A"); + } + + @Test + void test3() { + assertEquals(LongestPalindromicSubsequence.LPS("BABCBAB"), "BABCBAB"); + } + + @Test + void test4() { + assertEquals(LongestPalindromicSubsequence.LPS("BBABCBCAB"), "BABCBAB"); + } + + @Test + void test5() { + assertEquals(LongestPalindromicSubsequence.LPS("AAAAAAAAAAAAAAAAAAAAAAAA"), "AAAAAAAAAAAAAAAAAAAAAAAA"); + } +}