Can the string be segmented in JavaScript

The string segmentation problem determines if a given string can be broken down into words that exist in a provided dictionary. This is a classic dynamic programming problem with practical applications in natural language processing and text analysis.

What is String Segmentation?

String segmentation involves breaking a continuous string into meaningful words using a dictionary. For example, given the string "haveapplepie" and dictionary ["have", "apple", "pie"], we can segment it as "have" + "apple" + "pie".

// Example visualization
const dictionary = ["apple", "have", "pie"];
const input = "haveapplepie";
// Can be segmented as: "have" + "apple" + "pie"
console.log("Segmentation possible: true");
Segmentation possible: true

Brute Force Approach

The simplest approach uses recursion to try all possible segmentations:

function canSegment(str, dictionary) {
    // Base case: empty string can always be segmented
    if (str.length === 0) return true;
    
    // Try all possible first words
    for (let i = 1; i <= str.length; i++) {
        let firstWord = str.substring(0, i);
        let remaining = str.substring(i);
        
        // If first word exists in dictionary and remaining can be segmented
        if (dictionary.includes(firstWord) && canSegment(remaining, dictionary)) {
            return true;
        }
    }
    
    return false;
}

const dictionary = ["apple", "have", "pie"];
const testString = "haveapplepie";

console.log(canSegment(testString, dictionary));
true

Optimized Approach with Memoization

The brute force approach has exponential time complexity O(2^n). We can optimize it using memoization to achieve O(n²) complexity:

function canSegmentOptimized(str, dictionary) {
    const memo = {};
    
    function helper(start) {
        // Base case: reached end of string
        if (start === str.length) return true;
        
        // Check memoization
        if (memo[start] !== undefined) return memo[start];
        
        // Try all possible words starting from current position
        for (let end = start + 1; end <= str.length; end++) {
            let word = str.substring(start, end);
            
            if (dictionary.includes(word) && helper(end)) {
                memo[start] = true;
                return true;
            }
        }
        
        memo[start] = false;
        return false;
    }
    
    return helper(0);
}

const dictionary = ["apple", "pen", "applepen"];
const testString = "applepenapple";

console.log("Can segment:", canSegmentOptimized(testString, dictionary));

// Test with different examples
const dictionary2 = ["cats", "dog", "sand", "and", "cat"];
console.log("catsanddogs:", canSegmentOptimized("catsanddog", dictionary2));
Can segment: true
catsanddogs: true

Dynamic Programming Approach

An iterative bottom-up approach using dynamic programming:

function canSegmentDP(str, dictionary) {
    const n = str.length;
    const dp = new Array(n + 1).fill(false);
    dp[0] = true; // Empty string can always be segmented
    
    for (let i = 1; i <= n; i++) {
        for (let j = 0; j < i; j++) {
            let word = str.substring(j, i);
            if (dp[j] && dictionary.includes(word)) {
                dp[i] = true;
                break;
            }
        }
    }
    
    return dp[n];
}

const dictionary = ["leet", "code"];
const testString = "leetcode";

console.log("DP approach result:", canSegmentDP(testString, dictionary));
DP approach result: true

Complexity Analysis

Approach Time Complexity Space Complexity
Brute Force O(2^n) O(n)
Memoization O(n²) O(n)
Dynamic Programming O(n²) O(n)

Complete Example

function stringSegmentation(str, dictionary) {
    const memo = {};
    
    function canBreak(start) {
        if (start === str.length) return true;
        if (memo[start] !== undefined) return memo[start];
        
        for (let end = start + 1; end <= str.length; end++) {
            let prefix = str.substring(start, end);
            if (dictionary.includes(prefix) && canBreak(end)) {
                return memo[start] = true;
            }
        }
        
        return memo[start] = false;
    }
    
    return canBreak(0);
}

// Test cases
const testCases = [
    { str: "leetcode", dict: ["leet", "code"] },
    { str: "applepenapple", dict: ["apple", "pen"] },
    { str: "catsanddogs", dict: ["cats", "dog", "sand", "and", "cat"] }
];

testCases.forEach(({ str, dict }, index) => {
    console.log(`Test ${index + 1}: "${str}" -> ${stringSegmentation(str, dict)}`);
});
Test 1: "leetcode" -> true
Test 2: "applepenapple" -> true
Test 3: "catsanddogs" -> false

Conclusion

String segmentation can be solved efficiently using dynamic programming with memoization, reducing complexity from O(2^n) to O(n²). This technique is valuable for word break problems and text processing applications.

Updated on: 2026-03-15T23:19:00+05:30

432 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements