mirror of
https://github.com/TheAlgorithms/Java.git
synced 2025-07-07 17:56:02 +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