Skip to content

Commit 98dcfae

Browse files
authored
Merge branch 'master' into master
2 parents f4fb745 + 6fbbc94 commit 98dcfae

5 files changed

Lines changed: 86 additions & 48 deletions

File tree

pmd-exclude.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ com.thealgorithms.others.MosAlgorithm=UselessMainMethod
8686
com.thealgorithms.others.PageRank=UselessMainMethod,UselessParentheses
8787
com.thealgorithms.others.PerlinNoise=UselessMainMethod,UselessParentheses
8888
com.thealgorithms.others.QueueUsingTwoStacks=UselessParentheses
89-
com.thealgorithms.others.Trieac=UselessMainMethod,UselessParentheses
89+
com.thealgorithms.datastructures.trees.TrieAutocomplete=UselessMainMethod,UselessParentheses
9090
com.thealgorithms.others.Verhoeff=UnnecessaryFullyQualifiedName,UselessMainMethod
9191
com.thealgorithms.recursion.DiceThrower=UselessMainMethod
9292
com.thealgorithms.searches.HowManyTimesRotated=UselessMainMethod

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@
119119
<plugin>
120120
<groupId>com.github.spotbugs</groupId>
121121
<artifactId>spotbugs-maven-plugin</artifactId>
122-
<version>4.9.8.3</version>
122+
<version>4.10.2.0</version>
123123
<configuration>
124124
<excludeFilterFile>spotbugs-exclude.xml</excludeFilterFile>
125125
<includeTests>true</includeTests>

src/main/java/com/thealgorithms/others/Implementing_auto_completing_features_using_trie.java renamed to src/main/java/com/thealgorithms/datastructures/trees/TrieAutocomplete.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
package com.thealgorithms.others;
1+
package com.thealgorithms.datastructures.trees;
22

33
// Java Program to implement Auto-Complete
44
// Feature using Trie
5-
class Trieac {
5+
class TrieAutocomplete {
66

77
// Alphabet size (# of symbols)
88
public static final int ALPHABET_SIZE = 26;
Lines changed: 28 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,42 @@
11
package com.thealgorithms.dynamicprogramming;
22

33
/**
4-
* Algorithm explanation
5-
* https://www.educative.io/edpresso/longest-palindromic-subsequence-algorithm
4+
* Longest Palindromic Subsequence algorithm.
5+
* A palindromic subsequence is a subsequence that reads the same forwards and backwards.
6+
* This implementation finds the longest such subsequence by computing the LCS of the
7+
* original string and its reverse.
8+
*
9+
* @see <a href="https://en.wikipedia.org/wiki/Longest_palindromic_subsequence">Wikipedia</a>
610
*/
711
public final class LongestPalindromicSubsequence {
812
private LongestPalindromicSubsequence() {
913
}
1014

11-
public static void main(String[] args) {
12-
String a = "BBABCBCAB";
13-
String b = "BABCBAB";
14-
15-
String aLPS = lps(a);
16-
String bLPS = lps(b);
17-
18-
System.out.println(a + " => " + aLPS);
19-
System.out.println(b + " => " + bLPS);
20-
}
21-
22-
public static String lps(String original) throws IllegalArgumentException {
23-
StringBuilder reverse = new StringBuilder(original);
24-
reverse = reverse.reverse();
25-
return recursiveLPS(original, reverse.toString());
15+
/**
16+
* Returns the longest palindromic subsequence of the given string.
17+
*
18+
* @param original the input string
19+
* @return the longest palindromic subsequence
20+
* @throws IllegalArgumentException if the input string is null
21+
*/
22+
public static String lps(String original) {
23+
if (original == null) {
24+
throw new IllegalArgumentException("Input string must not be null");
25+
}
26+
String reverse = new StringBuilder(original).reverse().toString();
27+
return recursiveLPS(original, reverse);
2628
}
2729

2830
private static String recursiveLPS(String original, String reverse) {
29-
String bestResult = "";
30-
31-
// no more chars, then return empty
32-
if (original.length() == 0 || reverse.length() == 0) {
33-
bestResult = "";
34-
} else {
35-
// if the last chars match, then remove it from both strings and recur
36-
if (original.charAt(original.length() - 1) == reverse.charAt(reverse.length() - 1)) {
37-
String bestSubResult = recursiveLPS(original.substring(0, original.length() - 1), reverse.substring(0, reverse.length() - 1));
38-
39-
bestResult = reverse.charAt(reverse.length() - 1) + bestSubResult;
40-
} else {
41-
// otherwise (1) ignore the last character of reverse, and recur on original and
42-
// updated reverse again (2) ignore the last character of original and recur on the
43-
// updated original and reverse again then select the best result from these two
44-
// subproblems.
45-
46-
String bestSubResult1 = recursiveLPS(original, reverse.substring(0, reverse.length() - 1));
47-
String bestSubResult2 = recursiveLPS(original.substring(0, original.length() - 1), reverse);
48-
if (bestSubResult1.length() > bestSubResult2.length()) {
49-
bestResult = bestSubResult1;
50-
} else {
51-
bestResult = bestSubResult2;
52-
}
53-
}
31+
if (original.isEmpty() || reverse.isEmpty()) {
32+
return "";
5433
}
55-
56-
return bestResult;
34+
if (original.charAt(original.length() - 1) == reverse.charAt(reverse.length() - 1)) {
35+
String bestSubResult = recursiveLPS(original.substring(0, original.length() - 1), reverse.substring(0, reverse.length() - 1));
36+
return reverse.charAt(reverse.length() - 1) + bestSubResult;
37+
}
38+
String sub1 = recursiveLPS(original, reverse.substring(0, reverse.length() - 1));
39+
String sub2 = recursiveLPS(original.substring(0, original.length() - 1), reverse);
40+
return sub1.length() >= sub2.length() ? sub1 : sub2;
5741
}
5842
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package com.thealgorithms.dynamicprogramming;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
import static org.junit.jupiter.api.Assertions.assertThrows;
5+
6+
import org.junit.jupiter.api.Test;
7+
import org.junit.jupiter.params.ParameterizedTest;
8+
import org.junit.jupiter.params.provider.CsvSource;
9+
10+
public class LongestPalindromicSubsequenceTest {
11+
12+
@ParameterizedTest
13+
@CsvSource({"BBABCBCAB, BACBCAB", "BABCBAB, BABCBAB", "A, A", "AA, AA", "AB, B"})
14+
void testLpsKnownCases(String input, String expectedLps) {
15+
assertEquals(expectedLps, LongestPalindromicSubsequence.lps(input));
16+
}
17+
18+
@Test
19+
void testLpsEmptyString() {
20+
assertEquals("", LongestPalindromicSubsequence.lps(""));
21+
}
22+
23+
@Test
24+
void testLpsSingleCharacter() {
25+
assertEquals("Z", LongestPalindromicSubsequence.lps("Z"));
26+
}
27+
28+
@Test
29+
void testLpsAllSameCharacters() {
30+
assertEquals("AAAA", LongestPalindromicSubsequence.lps("AAAA"));
31+
}
32+
33+
@Test
34+
void testLpsAlreadyPalindrome() {
35+
assertEquals("RACECAR", LongestPalindromicSubsequence.lps("RACECAR"));
36+
}
37+
38+
@Test
39+
void testLpsNoRepeatingCharacters() {
40+
assertEquals(1, LongestPalindromicSubsequence.lps("ABCDE").length());
41+
}
42+
43+
@Test
44+
void testLpsNullThrowsException() {
45+
assertThrows(IllegalArgumentException.class, () -> { LongestPalindromicSubsequence.lps(null); });
46+
}
47+
48+
@Test
49+
void testLpsResultIsActuallyPalindrome() {
50+
String result = LongestPalindromicSubsequence.lps("BBABCBCAB");
51+
String reversed = new StringBuilder(result).reverse().toString();
52+
assertEquals(result, reversed);
53+
}
54+
}

0 commit comments

Comments
 (0)