Skip to content

Commit 0d68b65

Browse files
Tuhinm2002alxkm
andauthored
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 <[email protected]>
1 parent 0b86774 commit 0d68b65

File tree

2 files changed

+113
-0
lines changed

2 files changed

+113
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
package com.thealgorithms.dynamicprogramming;
2+
3+
import java.util.Arrays;
4+
import java.util.HashSet;
5+
import java.util.Set;
6+
7+
/**
8+
* Utility class to find the number of unique subsequences that can be
9+
* produced from a given string.
10+
*
11+
* <p> This class contains static methods to compute the unique subsequence count
12+
* using dynamic programming and recursion. It ensures that duplicate characters
13+
* are not counted multiple times in the subsequences.</p>
14+
*
15+
* <p> Author: https://github.com/Tuhinm2002 </p>
16+
*/
17+
public final class UniqueSubsequencesCount {
18+
19+
/**
20+
* Private constructor to prevent instantiation of this utility class.
21+
* This class should only be used in a static context.
22+
*
23+
* @throws UnsupportedOperationException if attempted to instantiate.
24+
*/
25+
private UniqueSubsequencesCount() {
26+
throw new UnsupportedOperationException("Utility class");
27+
}
28+
29+
/**
30+
* Finds the number of unique subsequences that can be generated from
31+
* the given string.
32+
*
33+
* <p> This method initializes a dynamic programming (DP) array and invokes
34+
* the recursive helper function to compute the subsequence count.</p>
35+
*
36+
* @param str the input string from which subsequences are generated
37+
* @return the total count of unique subsequences
38+
*/
39+
public static int countSubseq(String str) {
40+
41+
// DP array initialized to store intermediate results
42+
int[] dp = new int[str.length() + 1];
43+
Arrays.fill(dp, -1);
44+
45+
// Calls the recursive function to compute the result
46+
return countSubsequences(str, 0, dp);
47+
}
48+
49+
/**
50+
* Recursive helper function to count the number of unique subsequences
51+
* starting from the given index.
52+
*
53+
* <p> Uses a HashSet to avoid counting duplicate characters within
54+
* a single subsequence.</p>
55+
*
56+
* @param st the input string
57+
* @param idx the current index from which to calculate subsequences
58+
* @param dp dynamic programming array used to memoize results
59+
* @return the total number of unique subsequences starting from the
60+
* current index
61+
*/
62+
public static int countSubsequences(String st, int idx, int[] dp) {
63+
64+
// Base case: when index exceeds the string length
65+
if (idx >= st.length()) {
66+
return 0;
67+
}
68+
69+
// If result is already calculated, return the memoized value
70+
if (dp[idx] != -1) {
71+
return dp[idx];
72+
}
73+
74+
// Set to store characters to avoid duplicates
75+
Set<Character> set = new HashSet<>();
76+
77+
int res = 0;
78+
79+
// Iterate over the string starting from current index
80+
for (int j = idx; j < st.length(); j++) {
81+
82+
// If character is already in the set, skip it
83+
if (set.contains(st.charAt(j))) {
84+
continue;
85+
}
86+
87+
// Add character to set and recursively calculate subsequences
88+
set.add(st.charAt(j));
89+
90+
// 1 for the current subsequence + recursive call for the rest of the string
91+
res = 1 + countSubsequences(st, j + 1, dp) + res;
92+
}
93+
94+
// Memoize the result
95+
dp[idx] = res;
96+
return dp[idx];
97+
}
98+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.thealgorithms.dynamicprogramming;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
5+
import org.junit.jupiter.params.ParameterizedTest;
6+
import org.junit.jupiter.params.provider.CsvSource;
7+
8+
public class UniqueSubsequencesCountTest {
9+
10+
@ParameterizedTest
11+
@CsvSource({"abc, 7", "abcdashgdhas, 3592", "a, 1", "'a b', 7", "a1b2, 15", "AaBb, 15", "abab, 11"})
12+
void subseqCountParameterizedTest(String input, int expected) {
13+
assertEquals(expected, UniqueSubsequencesCount.countSubseq(input));
14+
}
15+
}

0 commit comments

Comments
 (0)