问题:
Given a string s and a dictionary of words dict, add spaces in s to construct a sentence where each word is a valid dictionary word.
Return all such possible sentences.
For example, given
s = "catsanddog"
,
dict = ["cat", "cats", "and", "sand", "dog"]
.
A solution is ["cats and dog", "cat sand dog"]
.
其实我是先看到这个题目,做了,后来才做wordbreak 的。所以具体思路和word break一样。先构建有效子序列的判断矩阵,之后找有效路径,所不同的是这次要保存有效路径。
所以主要改了最后的递归函数。但是一直没有A让我烦心好久。后来发现是因为set本身的原因,set本身按从小到大排序,结果oj上的结果是按从大到小。我以为是按字典序,还特意去写了字典序呢。
class Solution {
vector<string> result;
int **judge;
int *size;
void addResult(string str, int start, string item)
{
if(start == str.length())
{
result.push_back(item.substr(0,item.length()));
}
else
{
for(int k = 0; k < size[start]; k++)
{
int end = judge[start][k];
if(item.length() > 0 && item.substr(item.length()-1,1).compare(" ") != 0) item +=" ";
item += str.substr(start,end-start+1);
addResult(str, end+1,item);
item = item.substr(0,item.length()-end+start-1);
}
}
}
public:
vector<string> wordBreak(string s, unordered_set<string> &dict)
{
if(s.length() == 0 || dict.size() == 0) return result;
int len = s.length();
judge = new int*[len];
size = new int[len];
memset(size, 0, len*sizeof(int));
bool flag = false;
for(int i = 0; i < len; i++)
{
judge[i] = new int[len];
for(unordered_set<string>::iterator it = dict.begin(); it != dict.end(); it++)
{
int wordlen = it->length();
if(i + wordlen <= len &&
it->compare(s.substr(i,wordlen)) == 0)
{
judge[i][size[i]++] = i+ wordlen-1;
if(i + wordlen == len) flag = true;
}
}
}
if(flag == true) // 存在
addResult(s,0,"");
for(int i = 0; i < len; i++)
delete judge[i];
delete judge;
delete size;
vector<string> res;
for(int i = result.size() - 1; i >=0; i--)
res.push_back(result[i]);
return res;
}
};
今天总算把前两天积压的问题A过了,还发现了一个意外就是VS编译器和DevC++在处理set上市不一样的。VS中unorderset遍历可以按原本顺序,Dev中如果没导入库,仅仅支持set,而且会有默认排序,所以无法得到原本输入的顺序。伤不起的累了