Extra Characters in a String — Medium Problem & Solution
You are given a string s and a list of words dictionary. Break s into one or more non-overlapping substrings such that each substring is a word in…
- Difficulty: Medium
- Topics: Strings, Dynamic Programming, Hash Table, Trie
- Asked at: Amazon, Google, Adobe
- Time limit: 2 s
- Memory limit: 256 MB
- Languages: JavaScript, TypeScript, Python, Java, C++, C, C#, Go, Kotlin, Swift, Rust, PHP and Ruby
Problem statement
You are given a string s and a list of words dictionary. Break s into one or more non-overlapping substrings such that each substring is a word in dictionary; characters of s that end up in no chosen substring are extra.
Return the minimum possible number of extra characters.
Example 1
Input: s = "dsaroadmap", dictionary = ["road","map","ds"]
Output: 1
Explanation: `ds` + `road` + `map` leave only the `a` at index 2 unused.
Example 2
Input: s = "sayhelloworld", dictionary = ["hello","world"]
Output: 3
Explanation: `say` is left over.
Example 3
Input: s = "codekairo", dictionary = ["code","kair","kai","ro"]
Output: 0
Constraints
1 <= s.length <= 501 <= dictionary.length <= 501 <= dictionary[i].length <= 50dictionary[i] and s consist of only lowercase English lettersdictionary contains distinct words
How to solve Extra Characters in a String
Suffix DP over positions: at each index you either throw the character away or consume a whole dictionary word that starts there.
Approach
dp[n] = 0.- For
i = n-1down to 0: start withdp[i] = 1 + dp[i + 1]. - For each dictionary word
wwithsstarting withwati, setdp[i] = min(dp[i], dp[i + |w|]). - Return
dp[0].
Why it works
In an optimal break-up, position i is either unused (cost 1 plus the best for the rest) or the start of some chosen word, after which the rest is again an independent suffix problem. The DP tries both, so it finds the optimum.
Complexity
- Time —
O(n · D · L) — n positions, D words of length up to L (a trie makes it O(n²)) - Space —
O(n)
Pitfalls
- Greedily taking the longest word that matches can be wrong — a shorter word may let a later word fit.
- Words may be longer than the rest of
s; check bounds before comparing. - Characters inside a chosen word are never extra, but chosen words cannot overlap.
Reference solution
Python
from typing import List
def minExtraChar(s: str, dictionary: List[str]) -> int:
n = len(s)
dp = [0] * (n + 1)
for i in range(n - 1, -1, -1):
best = 1 + dp[i + 1]
for w in dictionary:
if s.startswith(w, i) and dp[i + len(w)] < best:
best = dp[i + len(w)]
dp[i] = best
return dp[0]JavaScript
var minExtraChar = function(s, dictionary) {
var n = s.length;
var dp = new Array(n + 1).fill(0);
for (var i = n - 1; i >= 0; i--) {
var best = 1 + dp[i + 1];
for (var k = 0; k < dictionary.length; k++) {
var w = dictionary[k];
if (i + w.length <= n && s.substr(i, w.length) === w && dp[i + w.length] < best) best = dp[i + w.length];
}
dp[i] = best;
}
return dp[0];
};Also on the editorial tab: C, C#, C++, Go, Java, Kotlin, PHP, Ruby, Rust, Swift, TypeScript.
All 424 strings problems · the whole catalogue
Learn the technique: Strings · Dynamic Programming