Word Break

Given a string s and a dictionary of words dict, determine if s can be segmented into a space-separated sequence of one or more dictionary words.

For example, given
s = "leetcode",
dict = ["leet", "code"].

Return true because "leetcode" can be segmented as "leet code".

思路:DP。

维护一个一维bool类型数组DP[]。DP[i]表示字符串S从第0位到第i位子串是否能够分割成字典里的单词。

然后遍历一遍字典,记录下字典中单词的最大长度和最小长度,分别记为max_l和min_l。

之后进行二重循环,外层循环枚举的是单词在S中的结束位置,因为已知最短的单词长为min_l,设S长为n,则枚举的范围是min_l - 1到n - 1。

内层循环枚举的是单词的开始位置,即以外层循环所枚举的结束位置为基准,向前找min_l到max_l的距离,更近或更远都不可能存在单词了。

这里注意一个点,内层循环在枚举了一个开始位置后,设其为i,若i不为0,则判断下dp[i - 1]是否为true,若为false则直接continue。因为若前面都无法由单词构成,则这里就算由单词构成也没什么用。

最后dp[n - 1]即为结果。

 1 class Solution {
 2 public:
 3     bool wordBreak(string s, unordered_set<string>& wordDict) {
 4         int n = s.size();
 5         if (n == 0) return false;
 6         vector<bool> dp(n, false);
 7         unordered_set<string>::iterator iter = wordDict.begin();
 8         unordered_set<string>::iterator end = wordDict.end();
 9         int max_l = INT_MIN;
10         int min_l = INT_MAX;
11         for (; iter != end; iter++)
12         {
13             int size = iter->size();
14             max_l = max(max_l, size);
15             min_l = min(min_l, size);
16         }
17         for (int i = min_l - 1; i < n; i++)
18             for (int j = i - min_l + 1; j >= 0 && j >= i - max_l + 1; j--)
19             {
20                 if (j - 1 >= 0 && !dp[j - 1]) continue;
21                 string word = s.substr(j, i - j + 1);
22                 if (wordDict.count(word) > 0) dp[i] = true;
23             }
24         return dp[n - 1];
25     }
26 };
原文地址:https://www.cnblogs.com/fenshen371/p/4904206.html