LintCode: Word Break
给定字符串序列和一个字典,问给定的字符串能否用字典中的单词拼出来?
图:
节点:字符串的前缀长度
边:前缀x如果加一个字典里边的单词能形成新前缀x',则有一条边
例如:字符串IAMxxxxx,字典里有I和AM
则有(0,1)一条边,(1,3)一条边
解:从(0,?)到(?,n)找一条路径
这是一个判断是否有解的问题
BFS/DFS
从当前前缀开始加一个单词
其他
能否dp?bool dp[x]表示能否连到x位置
dp[x] = dp[y] && (y..x是一个单词)
思考:
如何求一组解?全部解?
C++
DFS
(lintcode: s太长的话,会溢出。64bit mac OS上字符串长度超过8881就溢出。)
(leetcode: Accepted)
1 class Solution { 2 public: 3 bool help(string &s, int now, unordered_set<string> &d, vector<bool> &have) { 4 if (now >= s.length()) { 5 return true; 6 } 7 if (have[now]) { 8 return false; 9 } 10 have[now] = true; 11 for (int i = now; i < s.length(); ++i) { 12 if ((d.find(s.substr(now, i - now + 1)) != d.end()) && (help(s, i + 1, d, have))) { 13 return true; 14 } 15 } 16 return false; 17 } 18 /** 19 * @param s: A string s 20 * @param dict: A dictionary of words dict 21 */ 22 bool wordBreak(string s, unordered_set<string> &dict) { 23 // write your code here 24 vector<bool> have(s.length(), false); 25 return help(s, 0, dict, have); 26 } 27 };
C++
BFS
(lintcode:字符串太长,例如超过10000个字符,会超时)
(leetcode: Accepted)
1 class Solution { 2 public: 3 bool help(string &s, unordered_set<string> &d) { 4 if (0 == s.length()) { 5 return true; 6 } 7 vector<bool> have(s.length(), false); 8 have[0] = true; 9 queue<int> q; 10 for (q.push(0); !q.empty(); q.pop()) { 11 int now = q.front(); 12 for (int i = now; i < s.length(); ++i) { 13 if ((d.find(s.substr(now, i - now + 1)) != d.end())) { 14 if (i + 1 >= s.length()) { 15 return true; 16 } 17 if (!have[i + 1]) { 18 have[i + 1] = true; 19 q.push(i + 1); 20 } 21 } 22 } 23 } 24 25 return false; 26 } 27 /** 28 * @param s: A string s 29 * @param dict: A dictionary of words dict 30 */ 31 bool wordBreak(string s, unordered_set<string> &dict) { 32 // write your code here 33 return help(s, dict); 34 } 35 };
C++
DP
(lintcode:字符串太长,例如超过10000个字符,会超时)
(leetcode: Accepted)
1 class Solution { 2 public: 3 bool help(string &s, unordered_set<string> &d) { 4 if (0 == s.length()) { 5 return true; 6 } 7 vector<bool> dp(s.length(), false); 8 dp[0] = true; 9 for (int now = 0; now < s.length(); ++now) { 10 if (!dp[now]) { 11 continue; 12 } 13 for (int i = now; i < s.length(); ++i) { 14 if ((d.find(s.substr(now, i - now + 1)) != d.end())) { 15 if (i + 1 >= s.length()) { 16 return true; 17 } 18 dp[i + 1] = true; 19 } 20 } 21 } 22 23 return false; 24 } 25 /** 26 * @param s: A string s 27 * @param dict: A dictionary of words dict 28 */ 29 bool wordBreak(string s, unordered_set<string> &dict) { 30 // write your code here 31 return help(s, dict); 32 } 33 };
Python
DP
1 class Solution: 2 # @param s: A string s 3 # @param dict: A dictionary of words dict 4 def wordBreak(self, s, dict): 5 if len(dict) == 0: 6 return len(s) == 0 7 8 n = len(s) 9 f = [False] * (n + 1) 10 f[0] = True 11 12 maxLength = max([len(w) for w in dict]) 13 for i in xrange(1, n + 1): 14 for j in range(1, min(i, maxLength) + 1): 15 if not f[i - j]: 16 continue 17 if s[i - j:i] in dict: 18 f[i] = True 19 break 20 21 return f[n]
找我内推: 字节跳动各种岗位
作者:
ZH奶酪(张贺)
邮箱:
cheesezh@qq.com
出处:
http://www.cnblogs.com/CheeseZH/
*
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。