标签:
题目:
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"
.
代码:
class Solution { public: bool wordBreak(string s, unordered_set<string>& wordDict) { const int n = s.size(); vector<vector<bool> > dp(n,vector<bool>(n,false)); for ( int i=n-1; i>=0; --i ) { for ( int j=i; j<n; ++j ) { for ( int k=i; k<=j; ++k ) { if ( k==j && wordDict.find(s.substr(i,j-i+1))!=wordDict.end() ) { dp[i][j]=true; } else { dp[i][j] = dp[i][k] && dp[k+1][j]; if (dp[i][j]) break; } } } } return dp[0][n-1]; } };
tips:
用了一个二维dp的思路。
dp[i][j]表示s[i]到s[j]是否能被dict表示。
dp的顺序是从后往前走,相当于是从最下往上dp上三角阵。
求递推项dp[i][j]用一个循环遍历:dp[i][k] dp[k+1][j] ( i <= k <= j )如果能找到一个使得dp[i][j]为true,则跳出。
这里有一个corner case就是k==j的时候,dp[j+1][j]没有意义;因此特殊处理一下这种case,直接查找dict中是否有s[i:j]。
完成之后,在思考这道题是否可以用滚动数组来做?这样空间复杂度就降低为了O(n)
================================================
这个并不是滚动数组,就是一个一维DP,如下。
class Solution { public: bool wordBreak(string s, unordered_set<string>& wordDict) { const int n = s.size(); vector<bool> dp(n+1, false); dp[0] = true; for ( int i=1; i<=n; ++i ) { for ( int j=0; j<i; ++j ) { if ( dp[j] && wordDict.find(s.substr(j,i-j))!=wordDict.end() ) { dp[i] = true; break; } } } return dp[n]; } };
tips:
1. 空间复杂度由O(n²)降低到了O(n)
2. 代码更简洁了
并不是滚动数组,就是一维的DP,只不过dp[i]的取值要由dp[0:i-1]所有历史过程来决定。
标签:
原文地址:http://www.cnblogs.com/xbf9xbf/p/4553117.html