Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Counting matching substrings in JavaScript
Counting matching substrings in JavaScript is essential for text analysis and string manipulation tasks. This article explores different methods to count subsequences within a string, helping developers choose the most appropriate approach for their needs.
Problem Statement
We need a JavaScript function that counts subsequences in a given string. The function takes a string "str" and an array of strings "arr" as input. It examines each element in "arr" and determines how many strings are subsequences of "str".
A subsequence is formed by removing characters from the original string while maintaining the relative order of remaining characters.
Sample Input:
str = 'abracadabra'; arr = ['a', 'bra', 'cad', 'dab'];
Sample Output:
Output = 4;
Explanation: All elements in the array ('a', 'bra', 'cad', 'dab') are subsequences of 'abracadabra', so the count is 4.
Method 1: Brute-Force Approach
This approach generates all possible subsequences of the input string and checks if each exists in the target array. While comprehensive, it's computationally expensive for larger inputs.
function countSubsequences(str, arr) {
let count = 0;
// Generate all possible subsequences of the input string
function generateSubsequences(sub, index) {
if (index === str.length) {
// Check if the subsequence exists in the array
if (arr.includes(sub)) {
count++;
}
return;
}
// Include the current character in the subsequence
generateSubsequences(sub + str[index], index + 1);
// Exclude the current character from the subsequence
generateSubsequences(sub, index + 1);
}
// Start generating subsequences from the beginning of the string
generateSubsequences("", 0);
return count;
}
// Example usage:
const str = "abcde";
const arr = ["a", "ab", "bd", "abc", "acde", "eab"];
const result = countSubsequences(str, arr);
console.log(result);
5
Method 2: Two-Pointer Approach
This more efficient approach uses two pointers to traverse the target string and each candidate subsequence. It's faster because it doesn't generate all possible subsequences upfront.
function countValidSubsequences(arr, target) {
let count = 0;
for (let i = 0; i < arr.length; i++) {
const current = arr[i];
let j = 0; // pointer for current string
let k = 0; // pointer for target string
while (j < current.length && k < target.length) {
if (current[j] === target[k]) {
j++; // move both pointers when characters match
k++;
} else {
k++; // only move target pointer when no match
}
}
// If we've matched all characters in current string
if (j === current.length) {
count++;
}
}
return count;
}
// Example usage:
const str = "abcde";
const arr = ["a", "ab", "bd", "abc", "acde", "eab"];
const result = countValidSubsequences(arr, str);
console.log(result);
5
Comparison
| Method | Time Complexity | Space Complexity | Best For |
|---|---|---|---|
| Brute-Force | O(2^n * m) | O(2^n) | Small strings |
| Two-Pointer | O(n * m) | O(1) | Large datasets |
Conclusion
The two-pointer approach is generally preferred for its efficiency and lower memory usage. Use the brute-force method only when dealing with very small strings or when you need to generate all subsequences for other purposes.
