leetcode - 2707. Extra Characters in a String

Description

You are given a 0-indexed string s and a dictionary of words dictionary. You have to break s into one or more non-overlapping substrings such that each substring is present in dictionary. There may be some extra characters in s which are not present in any of the substrings.

Return the minimum number of extra characters left over if you break up s optimally.

Example 1:

Input: s = "leetscode", dictionary = ["leet","code","leetcode"]
Output: 1
Explanation: We can break s in two substrings: "leet" from index 0 to 3 and "code" from index 5 to 8. There is only 1 unused character (at index 4), so we return 1.

Example 2:

Input: s = "sayhelloworld", dictionary = ["hello","world"]
Output: 3
Explanation: We can break s in two substrings: "hello" from index 3 to 7 and "world" from index 8 to 12. The characters at indices 0, 1, 2 are not used in any substring and thus are considered as extra characters. Hence, we return 3.

Constraints:

1 <= s.length <= 50
1 <= dictionary.length <= 50
1 <= dictionary[i].length <= 50
dictionary[i] and s consists of only lowercase English letters
dictionary contains distinct words

Solution

Recursive

If we start with i, then f(i) = min(1 + f(i + 1), 2 + f(i + 2), ...) if s[i+1] not in dictionary. Use memory to speed up time.

Time complexity: o ( n ! ) o(n!) o(n!)
Space complexity: o ( n ) o(n) o(n)

DP

Use dp[i] to denote the answer for s[0:i], then transformation equation is:
d p [ i ] = min ⁡ ( d p [ i − k ] + { k ,      if s[i-k:i] not in dictionary 0 ,      else ) ,      ∀ k ∈ [ 1 , i ] dp[i] = \min(dp[i - k] + \begin{cases}k, \;\; \text{if s[i-k:i] not in dictionary} \\ 0, \;\; \text{else}\end{cases}), \;\; \forall k \in [1, i] dp[i]=min(dp[ik]+{k,if s[i-k:i] not in dictionary0,else),k[1,i]
Time complexity: o ( n 2 ) o(n^2) o(n2)
Space complexity: o ( n ) o(n) o(n)

Code

Recursive

class Solution:
    def minExtraChar(self, s: str, dictionary: List[str]) -> int:
        memo = {len(s): 0}
        def helper(s_index: int) -> int:
            if s_index in memo:
                return memo[s_index]
            res = []
            for i in range(s_index, len(s)):
                cur_prefix = s[s_index: i + 1]
                if cur_prefix not in dictionary:
                    res.append(len(cur_prefix) + helper(i + 1))
                else:
                    res.append(helper(i + 1))
            memo[s_index] = min(res)
            return memo[s_index]
        return helper(0)

DP

class Solution:
    def minExtraChar(self, s: str, dictionary: List[str]) -> int:
        dp = [i for i in range(len(s) + 1)]
        for i in range(1, len(s) + 1):
            for k in range(1, i + 1):
                prefix = s[i - k: i]
                dp[i] = min(dp[i], dp[i - k] + (k if prefix not in dictionary else 0))
        return dp[-1]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值