Leedcode12-word-break-i
发布日期:2025-04-04 18:31:36 浏览次数:11 分类:精选文章

本文共 1745 字,大约阅读时间需要 5 分钟。

动态规划是解决这类分割问题的有效方法。首先,我们创建一个布尔数组 dp,dp[i] 标记前 i 个字符是否可以分割成符合条件的词组。初始化 dp[0] = true,因为空字符串不需要分割。接着,对于每个位置 i(从 1 到 n),检查所有可能的 j 值(从 1 到 i),如果存在一个 j 使得 dp[i-j] 为 true,并且子串 s[i-j:i] 在词典中存在,那么 dp[i] 设为 true。最后返回 dp[n] 的值即可。

动态规划的实现步骤:

  • 初始化数组:创建长度为 n + 1 的 dp 数组,初始值为 false,dp[0] 设为 true。
  • 遍历字符串:从第一个字符开始,逐个处理到最后一个字符。
  • 检查所有可能的词长度:对于每个位置 i,检查从 1 到 i 的所有 j 值,查看是否存在使得 s[i-j:i] 是一个词。
  • 更新 dp 数组:如果找到符合条件的 j,设置 dp[i] 为 true,并继续下一个位置。
  • 终点判断:最终检查 dp[n] 是否为 true,返回相应结果。
  • 这种方法的时间复杂度为 O(n * m),其中 n 是字符串长度,m 是词典中的最大词长,适用于大部分实际问题。

    示例代码:

    #include 
    #include
    using namespace std;class Solution {public: bool wordBreak(string s, unordered_set
    dict) { int n = s.length(); if (n == 0) return false; vector
    dp(n + 1, false); dp[0] = true; // 空字符串可以分割 int max_word_len = 0; for (const string& word : dict) { if (word.length() > max_word_len) { max_word_len = word.length(); } } for (int i = 1; i <= n; ++i) { for (int j = 1; j <= max_word_len; ++j) { if (i - j < 0) continue; if (dp[i - j] && findInDict(s.substr(i - j, j), dict)) { dp[i] = true; break; } } } return dp[n]; } // 辅助函数,检查子串是否在字典中 bool findInDict(const string& substr, const unordered_set
    & dict) { return dict.find(substr) != dict.end(); }};

    优化考虑:

  • 使长度更优:通过记录词典中最长的词长,可以减少不必要的子串检查,提高效率。
  • 预先计算前缀:对于多次查询的场景,可以预先计算所有词的前缀,使用前缀哈希或滚动哈希来快速判断子串是否存在。
  • 设置边界:在处理每个位置时,避免超过字符串长度,防止越界错误。
  • 返回优化:一旦在某个位置找到了符合条件的分割,立即记录结果并继续处理后续位置,这可以节省时间。
  • 这种方法在处理较长字符串和较大词典时表现优异,是解决此类分割问题的经典方法。

    上一篇:Leedcode2-后缀表达式结果
    下一篇:Leedcode10-linked-list-cycle-ii

    发表评论

    最新留言

    路过按个爪印,很不错,赞一个!
    [***.219.124.196]2025年04月26日 03时39分20秒