Home/Learn/String Construction & Transformation

Pattern Guide

String Construction & Transformation

"Build target strings via DP. Edit distance, word ladder, minimum operations."

String construction problems ask: given a source, what is the minimum cost to build or transform into a target? Techniques: edit distance DP (insert/delete/replace), word ladder BFS, minimum operations to make string valid, constructing strings from dictionary, and rearrangement problems. Key insight: model valid states and transitions between them.

15 min readdp problems →

Problems you can solve with this pattern

5 problems · click any to start solving

All dp
1Edit DistanceMediumSolve
2Word LadderHardSolve
3Minimum Number of Steps to Make Two Strings AnagramMediumSolve
4Minimum ASCII Delete Sum for Two StringsMediumSolve
Edit distance and word break templates
// Edit distance — O(m*n)
function editDistance(s, t) {
    const m = s.length, n = t.length;
    const dp = Array.from({length: m+1}, (_, i) => Array(n+1).fill(0).map((_, j) => i||j));
    // dp[i][0]=i, dp[0][j]=j is implicit from the fill above; fix it:
    for (let i = 0; i <= m; i++) dp[i][0] = i;
    for (let j = 0; j <= n; j++) dp[0][j] = j;
    for (let i = 1; i <= m; i++) {
        for (let j = 1; j <= n; j++) {
            if (s[i-1] === t[j-1]) dp[i][j] = dp[i-1][j-1];
            else dp[i][j] = 1 + Math.min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]);
        }
    }
    return dp[m][n];
}

// Word break — can s be segmented using wordDict?
function wordBreak(s, wordDict) {
    const set = new Set(wordDict);
    const dp = new Array(s.length + 1).fill(false);
    dp[0] = true;
    for (let i = 1; i <= s.length; i++) {
        for (let j = 0; j < i; j++) {
            if (dp[j] && set.has(s.slice(j, i))) { dp[i] = true; break; }
        }
    }
    return dp[s.length];
}

Edit distance: dp[i][j] = min ops to convert s[0..i] to t[0..j]. Base: dp[i][0]=i, dp[0][j]=j. Transition: if s[i]==t[j], dp[i][j]=dp[i-1][j-1]; else min(dp[i-1][j]+1, dp[i][j-1]+1, dp[i-1][j-1]+1). Word ladder: BFS where each step changes one character to get a valid word. String construction from pieces: dp[i] = can build s[0..i] using dictionary words.

Edit distance and word break templates
// Edit distance — O(m*n)
function editDistance(s, t) {
    const m = s.length, n = t.length;
    const dp = Array.from({length: m+1}, (_, i) => Array(n+1).fill(0).map((_, j) => i||j));
    // dp[i][0]=i, dp[0][j]=j is implicit from the fill above; fix it:
    for (let i = 0; i <= m; i++) dp[i][0] = i;
    for (let j = 0; j <= n; j++) dp[0][j] = j;
    for (let i = 1; i <= m; i++) {
        for (let j = 1; j <= n; j++) {
            if (s[i-1] === t[j-1]) dp[i][j] = dp[i-1][j-1];
            else dp[i][j] = 1 + Math.min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]);
        }
    }
    return dp[m][n];
}

// Word break — can s be segmented using wordDict?
function wordBreak(s, wordDict) {
    const set = new Set(wordDict);
    const dp = new Array(s.length + 1).fill(false);
    dp[0] = true;
    for (let i = 1; i <= s.length; i++) {
        for (let j = 0; j < i; j++) {
            if (dp[j] && set.has(s.slice(j, i))) { dp[i] = true; break; }
        }
    }
    return dp[s.length];
}
String construction patterns:
- Edit distance: 2D DP, transitions on match vs mismatch
- Word ladder: BFS on word graph, change 1 char per step
- Decode ways: 1D DP, try 1-digit and 2-digit decodings
- Anagram steps: frequency difference sum

Edit distance variants: Weighted costs (ASCII delete sum), only insertions/deletions (LCS-based: cost = m+n - 2*LCS), one string to empty (just delete all).

Key optimization: For edit distance with only insert/delete, use LCS: min_ops = m + n - 2 * LCS(s, t).