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
Validating string with reference to array of words using JavaScript
We need to write a JavaScript function that takes an array of valid words and a string, then checks if the string can be formed by concatenating one or more words from the array.
Problem Statement
Given an array of words and a target string, determine if the string can be constructed using words from the array. Words can be reused multiple times.
Input:
const arr = ['love', 'coding', 'i']; const str = 'ilovecoding';
Expected Output:
true
The string "ilovecoding" can be formed by concatenating "i" + "love" + "coding".
Incorrect Approach (Original Code)
The original approach has a fundamental flaw - it sorts characters instead of checking word combinations:
const arr = ['love', 'coding', 'i'];
const str = 'ilovecoding';
// Flawed approach - sorts characters
const wrongValidString = (arr = [], str) => {
let arrStr = arr.join('');
arrStr = arrStr.split('').sort().join('');
str = str.split('').sort().join('');
return arrStr.includes(str);
};
console.log("Wrong approach:", wrongValidString(arr, str));
Wrong approach: false
Correct Approach Using Dynamic Programming
The proper solution uses dynamic programming to check all possible word combinations:
const arr = ['love', 'coding', 'i'];
const str = 'ilovecoding';
const validString = (words, target) => {
const dp = new Array(target.length + 1).fill(false);
dp[0] = true; // Empty string can always be formed
for (let i = 1; i <= target.length; i++) {
for (let word of words) {
if (i >= word.length &&
target.substring(i - word.length, i) === word &&
dp[i - word.length]) {
dp[i] = true;
break;
}
}
}
return dp[target.length];
};
console.log("Correct result:", validString(arr, str));
Correct result: true
How the Algorithm Works
The dynamic programming approach builds up solutions for substrings:
// Step-by-step visualization
const visualValidString = (words, target) => {
const dp = new Array(target.length + 1).fill(false);
dp[0] = true;
console.log("Target string:", target);
console.log("Available words:", words);
console.log("Initial DP array:", dp);
for (let i = 1; i <= target.length; i++) {
for (let word of words) {
if (i >= word.length) {
const substring = target.substring(i - word.length, i);
if (substring === word && dp[i - word.length]) {
dp[i] = true;
console.log(`Position ${i}: Found "${word}" ending here`);
break;
}
}
}
}
return dp[target.length];
};
visualValidString(['love', 'coding', 'i'], 'ilovecoding');
Target string: ilovecoding Available words: [ 'love', 'coding', 'i' ] Initial DP array: [ true, false, false, false, false, false, false, false, false, false, false, false ] Position 1: Found "i" ending here Position 5: Found "love" ending here Position 11: Found "coding" ending here
Testing with Different Cases
const testCases = [
{ words: ['cat', 'cats', 'dog', 'sand', 'and'], str: 'catsanddog', expected: true },
{ words: ['apple', 'pen'], str: 'applepenapple', expected: true },
{ words: ['cats', 'dog', 'sand', 'and', 'cat'], str: 'catsandog', expected: false }
];
testCases.forEach((test, index) => {
const result = validString(test.words, test.str);
console.log(`Test ${index + 1}: ${result === test.expected ? 'PASS' : 'FAIL'}`);
console.log(` Input: "${test.str}"`);
console.log(` Expected: ${test.expected}, Got: ${result}`);
});
Test 1: PASS Input: "catsanddog" Expected: true, Got: true Test 2: PASS Input: "applepenapple" Expected: true, Got: true Test 3: PASS Input: "catsandog" Expected: false, Got: false
Conclusion
Use dynamic programming to solve word break problems correctly. The key insight is building solutions incrementally for each position in the target string, checking if any word can complete a valid substring.
