30(May) String Subsequence
30. String Subsequence
The problem can be found at the following link: Question Link
Problem Description
Given two strings, s1
and s2
, count the number of subsequences of string s1
equal to string s2
. Return the total count modulo (10^9 + 7).
Example 1:
Input:
s1 = "geeksforgeeks"
s2 = "gks"
Output:
4
Explanation: We can pick characters from s1
as a subsequence from indices {0,3,4}, {0,3,12}, {0,11,12} and {8,11,12}. So total 4 subsequences of s1
that are equal to s2
.
My Approach
Initialization:
Create a memoization table
memo
of size(n+1) x (m+1)
initialized to -1, wheren
is the length ofs1
andm
is the length ofs2
.Define the modulo value
mod
as (10^9 + 7).
Dynamic Programming Function:
Use a recursive function
dp(i, j)
to calculate the number of ways to match the firsti
characters ofs1
with the firstj
characters ofs2
.Base cases:
If
j == 0
, return 1 since an emptys2
can be matched in one way.If
i == 0
, return 0 since a non-emptys2
cannot be matched with an emptys1
.
Recursive cases:
If
s1[i-1] == s2[j-1]
, updatememo[i][j]
with the sum ofdp(i-1, j-1)
anddp(i-1, j)
modulomod
.Otherwise, set
memo[i][j]
todp(i-1, j)
modulomod
.
Return:
Return
dp(n, m)
wheren
is the length ofs1
andm
is the length ofs2
.
Time and Auxiliary Space Complexity
Expected Time Complexity: O(n * m), where
n
andm
are the lengths of the stringss1
ands2
respectively. This is due to the nested loops iterating over the lengths of the strings.Expected Auxiliary Space Complexity: O(n * m), due to the memoization table storing results for each subproblem of sizes up to
n
andm
.
Code
C++
class Solution {
public:
int countWays(string s1, string s2) {
int n = s1.length(), m = s2.length();
vector<int> dp(m + 1, 0);
int mod = 1e9 + 7;
dp[0] = 1;
for (int i = 1; i <= n; i++) {
int prev = dp[0];
for (int j = 1; j <= m; j++) {
int temp = dp[j];
if (s1[i - 1] == s2[j - 1]) {
dp[j] = (prev + dp[j]) % mod;
}
prev = temp;
}
}
return dp[m] % mod;
}
};
Java
class Solution {
public static int countWays(String s1, String s2) {
int n = s1.length(), m = s2.length();
int[][] memo = new int[n + 1][m + 1];
for (int[] row : memo) {
Arrays.fill(row, -1);
}
int mod = 1_000_000_007;
return dp(n, m, s1, s2, memo, mod);
}
private static int dp(int i, int j, String s1, String s2, int[][] memo, int mod) {
if (j == 0) return 1;
if (i == 0) return 0;
if (memo[i][j] != -1) return memo[i][j];
if (s1.charAt(i - 1) == s2.charAt(j - 1)) {
memo[i][j] = (dp(i - 1, j - 1, s1, s2, memo, mod) + dp(i - 1, j, s1, s2, memo, mod)) % mod;
} else {
memo[i][j] = dp(i - 1, j, s1, s2, memo, mod) % mod;
}
return memo[i][j];
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int t = Integer.parseInt(br.readLine());
while (t-- > 0) {
String s1 = br.readLine();
String s2 = br.readLine();
Solution obj = new Solution();
int res = obj.countWays(s1, s2);
System.out.println(res);
}
}
}
Python
class Solution:
def countWays(self, s1: str, s2: str) -> int:
n, m = len(s1), len(s2)
memo = [[-1] * (m + 1) for _ in range(n + 1)]
mod = 10**9 + 7
def dp(i, j):
if j == 0:
return 1 # s2 is empty, one way to match
if i == 0:
return 0 # s1 is empty, no way to match
if memo[i][j] != -1:
return memo[i][j]
if s1[i - 1] == s2[j - 1]:
memo[i][j] = (dp(i - 1, j - 1) + dp(i - 1, j)) % mod
else:
memo[i][j] = dp(i - 1, j) % mod
return memo[i][j]
return dp(n, m)
Contribution and Support
For discussions, questions, or doubts related to this solution, feel free to connect on LinkedIn: Any Questions. Letβs make this learning journey more collaborative!
β If you find this helpful, please give this repository a star! β
πVisitor Count
Last updated