Problem
Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, determine if s can be segmented into a space-separated sequence of one or more dictionary words. You may assume the dictionary does not contain duplicate words.
For example, given
s = “leetcode”,
dict = [“leet”, “code”].Return true because “leetcode” can be segmented as “leet code”.
具体详见Leetcode
Analysis
想法
首先先确定此题可以使用动态规划算法。然后就要找到动态规划算法的状态转移方程。
然后,初步的想法是把字符串分成两部分,如果两部分都是可以分成词的组合,那么最后把两部分的字符串拼起来也可以分成一个个的词。所以就考虑把一个子问题 f(i,j) 分成很多个由 f(i,k) 和 f(k+1,j) 两个部分组成的子问题,然后只要k从i到j这个过程中,有一个k满足让 f(i,k) 和 f(k+1,j) 都为true,即都可以分成两个字符串,那么 f(i,j) 也可以分成一个个的字符串。所以,定义 f(i,j) 为字符串s中由位置i到位置j的子串是否能分解为字典中的词。状态转移方程可表示为:
f[i][j]=⋃i<=k<j{f(i,k)∧f(k+1,j)}
最终答案表示为 f[0][s.size()−1]
Complexity
时间复杂度:i,j,k三重循环,为
O(n3)
空间复杂度:f的bool数组,为
O(n2)
Code
class Solution {
public:
bool wordBreak(string s, vector<string>& wordDict) {
int size = s.size();
int** dp = new int*[size];
for (int i = 0; i < size; i++) {
dp[i] = new int[size];
for (int j = 0; j < size; j++) {
dp[i][j] = -1;
}
}
for (int i = 0; i < size; i++) {
for (int j = i; j < size; j++) {
dp[i][j] = 0;
for (int k = i; k < j; k++) {
if (dp[i][k] == -1) {
dp[i][k] = 0;
for (int q = 0; q < wordDict.size(); q++) {
if (wordDict[q] == s.substr(i,k-i+1)) {
dp[i][k] = 1;
break;
}
}
}
if (dp[k+1][j] == -1) {
dp[k+1][j] = 0;
for (int q = 0; q < wordDict.size(); q++) {
if (wordDict[q] == s.substr(k+1,j-k)) {
dp[k+1][j] = 1;
break;
}
}
}
if (dp[i][k]==1 && dp[k+1][j]==1) {
dp[i][j] = 1;
break;
}
}
if (dp[i][j] == 0) {
for (int q = 0; q < wordDict.size(); q++) {
if (wordDict[q] == s.substr(i,j-i+1)) {
dp[i][j] = 1;
break;
}
}
}
}
}
return dp[0][size-1];
}
};