[LeetCode] Word Break

本文介绍了如何使用动态规划解决单词拆分问题,并提供了三种解决方案:动态规划、深度优先搜索(DFS)和广度优先搜索(BFS)。通过减少检查次数优化算法效率。

The typical solution to this problem is to use Dynamic Programming. The state dp[i] represents whether s[0..i - 1] can be broken into words in wordDict and the state equation is:

dp[i] = true, if there exists j < i such that dp[j] = true and s.substr(j, i - j) is in wordDict

dp[i] = false, otherwise.

The code is as follows (we use minlen and maxlen to reduce the number of checks).

 1 class Solution {
 2 public:
 3     bool wordBreak(string s, unordered_set<string>& wordDict) {
 4         int n = s.length();
 5         vector<bool> dp(n + 1, false);
 6         dp[0] = true;
 7         for (string word : wordDict) {
 8             minlen = min(minlen, (int)word.length());
 9             maxlen = max(maxlen, (int)word.length());
10         }
11         for (int i = 1; i <= n; i++) {
12             for (int j = i - minlen; j >= max(0, j - maxlen); j--) {
13                 if (dp[j] && wordDict.find(s.substr(j, i - j)) != wordDict.end()) {
14                     dp[i] = true;
15                     break;
16                 }
17             }
18         }
19         return dp[n];
20     }
21 private:
22     int minlen, maxlen;
23 };

This problem can also be solved using DFS or BFS.

DFS:

 1 class Solution {
 2 public:
 3     bool wordBreak(string s, unordered_set<string>& wordDict) {
 4         for (string word : wordDict) {
 5             minlen = min(minlen, (int)word.length());
 6             maxlen = max(maxlen, (int)word.length());
 7         }
 8         unordered_map<string, bool> records;
 9         return wordBreakDFS(s, 0, wordDict, records);
10     }
11 private:
12     int minlen, maxlen;
13     bool wordBreakDFS(string& s, int idx, unordered_set<string>& wordDict, unordered_map<string, bool>& records) {
14         int n = s.length();
15         if (idx == n) return true;
16         string tail = s.substr(idx, n - idx);
17         if (records.find(tail) != records.end())
18             return records[tail];
19         for (int i = idx + minlen; i <= min(idx + maxlen, n); i++) {
20             string part = s.substr(idx, i - idx);
21             if (wordDict.find(part) != wordDict.end() && wordBreakDFS(s, i, wordDict, records))
22                 return records[part] = true;
23         }
24         return records[tail] = false;
25     }
26 };

BFS:

 1 class Solution {
 2 public:
 3     bool wordBreak(string s, unordered_set<string>& wordDict) {
 4         int n = s.length();
 5         for (string word : wordDict) {
 6             minlen = min(minlen, (int)word.length());
 7             maxlen = max(maxlen, (int)word.length());
 8         }
 9         queue<int> toVisit;
10         unordered_set<int> visited;
11         toVisit.push(0);
12         while (!toVisit.empty()) {
13             int start = toVisit.front();
14             toVisit.pop();
15             if (visited.find(start) == visited.end()) {
16                 visited.insert(start);
17                 for (int end = start + minlen - 1; end < min(start + maxlen, n); end++) {
18                     string part = s.substr(start, end - start + 1);
19                     if (wordDict.find(part) != wordDict.end()) {
20                         if (end + 1 == n) return true;
21                         toVisit.push(end + 1);
22                     }
23                 }
24             }
25         }
26         return false;
27     }
28 private:
29     int minlen, maxlen;
30 };

 

转载于:https://www.cnblogs.com/jcliBlogger/p/4615620.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值