mirror of
https://github.com/TheAlgorithms/Java.git
synced 2025-07-06 17:29:31 +08:00
feat : new dp algo added UniqueSubsequenceCount.java
(#5586)
* feat : new algo uniquesubseqcount * Update UniqueSubsequencesCount.java * Update UniqueSubsequencesCountTest.java * Update UniqueSubsequencesCount.java * Update UniqueSubsequencesCount.java * Update UniqueSubsequencesCount.java * Update UniqueSubsequencesCount.java * Update UniqueSubsequencesCount.java * Update UniqueSubsequencesCount.java * Update UniqueSubsequencesCountTest.java * Update UniqueSubsequencesCount.java * Update UniqueSubsequencesCountTest.java * Update UniqueSubsequencesCount.java * Update UniqueSubsequencesCountTest.java * Update UniqueSubsequencesCountTest.java * Update UniqueSubsequencesCountTest.java * Update UniqueSubsequencesCount.java --------- Co-authored-by: Alex Klymenko <alexanderklmn@gmail.com>
This commit is contained in:
@ -0,0 +1,98 @@
|
||||
package com.thealgorithms.dynamicprogramming;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Utility class to find the number of unique subsequences that can be
|
||||
* produced from a given string.
|
||||
*
|
||||
* <p> This class contains static methods to compute the unique subsequence count
|
||||
* using dynamic programming and recursion. It ensures that duplicate characters
|
||||
* are not counted multiple times in the subsequences.</p>
|
||||
*
|
||||
* <p> Author: https://github.com/Tuhinm2002 </p>
|
||||
*/
|
||||
public final class UniqueSubsequencesCount {
|
||||
|
||||
/**
|
||||
* Private constructor to prevent instantiation of this utility class.
|
||||
* This class should only be used in a static context.
|
||||
*
|
||||
* @throws UnsupportedOperationException if attempted to instantiate.
|
||||
*/
|
||||
private UniqueSubsequencesCount() {
|
||||
throw new UnsupportedOperationException("Utility class");
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the number of unique subsequences that can be generated from
|
||||
* the given string.
|
||||
*
|
||||
* <p> This method initializes a dynamic programming (DP) array and invokes
|
||||
* the recursive helper function to compute the subsequence count.</p>
|
||||
*
|
||||
* @param str the input string from which subsequences are generated
|
||||
* @return the total count of unique subsequences
|
||||
*/
|
||||
public static int countSubseq(String str) {
|
||||
|
||||
// DP array initialized to store intermediate results
|
||||
int[] dp = new int[str.length() + 1];
|
||||
Arrays.fill(dp, -1);
|
||||
|
||||
// Calls the recursive function to compute the result
|
||||
return countSubsequences(str, 0, dp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursive helper function to count the number of unique subsequences
|
||||
* starting from the given index.
|
||||
*
|
||||
* <p> Uses a HashSet to avoid counting duplicate characters within
|
||||
* a single subsequence.</p>
|
||||
*
|
||||
* @param st the input string
|
||||
* @param idx the current index from which to calculate subsequences
|
||||
* @param dp dynamic programming array used to memoize results
|
||||
* @return the total number of unique subsequences starting from the
|
||||
* current index
|
||||
*/
|
||||
public static int countSubsequences(String st, int idx, int[] dp) {
|
||||
|
||||
// Base case: when index exceeds the string length
|
||||
if (idx >= st.length()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// If result is already calculated, return the memoized value
|
||||
if (dp[idx] != -1) {
|
||||
return dp[idx];
|
||||
}
|
||||
|
||||
// Set to store characters to avoid duplicates
|
||||
Set<Character> set = new HashSet<>();
|
||||
|
||||
int res = 0;
|
||||
|
||||
// Iterate over the string starting from current index
|
||||
for (int j = idx; j < st.length(); j++) {
|
||||
|
||||
// If character is already in the set, skip it
|
||||
if (set.contains(st.charAt(j))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add character to set and recursively calculate subsequences
|
||||
set.add(st.charAt(j));
|
||||
|
||||
// 1 for the current subsequence + recursive call for the rest of the string
|
||||
res = 1 + countSubsequences(st, j + 1, dp) + res;
|
||||
}
|
||||
|
||||
// Memoize the result
|
||||
dp[idx] = res;
|
||||
return dp[idx];
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package com.thealgorithms.dynamicprogramming;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.CsvSource;
|
||||
|
||||
public class UniqueSubsequencesCountTest {
|
||||
|
||||
@ParameterizedTest
|
||||
@CsvSource({"abc, 7", "abcdashgdhas, 3592", "a, 1", "'a b', 7", "a1b2, 15", "AaBb, 15", "abab, 11"})
|
||||
void subseqCountParameterizedTest(String input, int expected) {
|
||||
assertEquals(expected, UniqueSubsequencesCount.countSubseq(input));
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user