My first solution was DFS - TLE. Apparently, DFS with TLE usually means DP.
1D DP + Rolling Array:
class Solution { public: bool wordBreak(string s, unordered_set<string> &dict) { int len = s.length(); int lend= dict.size(); if(len == 0 || lend == 0) return false; // Init vector<bool> rec0, rec1; rec0.resize(len); rec1.resize(len); std::fill(rec0.begin(), rec0.end(), false); std::fill(rec1.begin(), rec1.end(), false); // vector<bool> &pre = rec0; vector<bool> &post = rec1; // Start from 0 for(int i = 1; i <= len; i ++) { string sub = s.substr(0, i); if(dict.find(sub) != dict.end()) { pre[i-1] = true; if(i == len) return true; } } for(int i = 1; i < len; i ++) // vertical { for(int j = 0; j < len; j ++) // horizontal { if(pre[j]) { for(int k = 1; k < len - j; k ++) { string sub = s.substr(j + 1, k); if(dict.find(sub) != dict.end()) { post[j + k] = true; if((j + k + 1) == len) return true; } } } } // Rolling array if(i % 2) { pre = rec1; post = rec0; } else { pre = rec0; post = rec1; } } return false; } };
Update on Nov 28 2014: much shorter code:
class Solution { vector<int> rec; public: bool wordBreak(string s, unordered_set<string> &dict) { if (s.length() == 0 || dict.size() == 0) return false; size_t len = s.length(); rec.push_back(0); // per length for (int i = 1; i <= len; i++) { for (int j = rec.size() - 1; j >= 0; j--) { if ( (i > rec[j] )) { string rest = s.substr(rec[j], i - rec[j]); if (dict.find(rest) != dict.end()) { rec.push_back(i); break; } } } } return rec.back() == len; } };