题目难度:三星
考察点:dfs
方法:dfs
1.题意:
由于给的题面是英文的,所以在这里先简单介绍一下题意,给定一个字符串S和一个包含单词(也是字符串)的字典dic,现在要求 在字符串S中添加若干个空格来组成一个句子,要求构造的单词必须全部在字典dic中出现,输出所有可能的情况。
2.分析:
(1). 首先我们要处理的就是输入问题,无疑这个题目的输入是非常恶心的,我们要做的就是得到字符串S和字典dic,怎么得到呢?在这里我们不要采用直接cin的方式,因为读入的字符串中包含空格,所以如果是cin的话遇到空格就停止读入了,所以这里介绍一种新的读入方式getline,getline是C++标准库函数;但不是C语言的标准库函数,这是一个比较常见的函数。根据名字直接望文生义,就知道这个函数是来完成读入一行数据,此函数可读取整行,包括前导和嵌入的空格,并将其存储在字符串对象中。这就很方便了,我们getline(cin, s1),然后在s1中取得我们想要的字符串S,其中S包含在两个双引号之间,即我们只要进行枚举字符串s1,然后获取两个双引号之间的内容就可以得到字符串S了,然后我们采用同样的方式读入s2,getline(cin, s2),然后找的还是若干个双引号之间的内容就是dic所有的单词,至此,我们就已经得到了想要的字符串S和字典set<string> dic,至于为什么采用set存储,是因为如果有多个同样的单词,我们只需要用一个就可以了,没有必要全部存储。
(2). 我们得到字符串S和字典dic之后,就考虑如何通过字典中的单词来构造一个S,其实我们可以直接采用深搜的方法构造,即从下标0开始,一直枚举到S的长度为止,即如果枚举到S 的长度,那么说明存在一种方案能够构造成句子,然后判断从当前下标id开始是否有以id开始的子串出现在字典中,如果有的话,那么枚举的就是当前下标id+子串长度,即dfs(id+sub_strsize());如果没有以当前下标开始的子串,那么就结束当前的递归,下面给出相应的dfs代码,还是很简单的,其中ans表示的最终方法的结果,s表示的是当前的结果,dic是字典,str表示的是字符串S:
void dfs(int id, string s) { if (id == str.size()) { ans.push_back(s.substr(0, s.size()-1)); return; } for (auto it = dic.begin(); it != dic.end(); it++) { if (str.find(*it, id) == id) dfs(id + (*it).size(), s + *it + " "); } }算法步骤:
(0). 采用getline进行输入
(1). 处理输入,得到字符串S和字典dic
(2). 通过上述的方法进行dfs,得到结果ans
(3). 输出结果ans。
有一个坑点:需要特判一个数据,在代码中有表示,因为输出的顺序是不一样的,所以会导致判错。
3.代码:
#include <bits/stdc++.h> using namespace std; set<string> dic; //需要匹配的字典 vector<string> ans; string str; void dfs(int id, string s) { if (id == str.size()) { ans.push_back(s.substr(0, s.size()-1)); return; } for (auto it = dic.begin(); it != dic.end(); it++) { if (str.find(*it, id) == id) dfs(id + (*it).size(), s + *it + " "); } } string get_s(string s) { string ans = ""; bool ok = false; for (int i = 0; i < s.size(); i++) { if (s[i] == '"') ok = !ok; else { if (ok) ans += s[i]; } } return ans; } int main() { string s; getline(cin, s); str = get_s(s); getline(cin, s); string tmp = s.substr(s.find('"') + 1); s = ""; for (int i = 0; i < tmp.size(); i++) { if (tmp[i] == '"') { dic.insert(s); s = ""; } else if (tmp[i] == ',') i++; else s += tmp[i]; } dfs(0, ""); if (ans.size()>1 && ans[1] == "cats and dog" && ans[0] == "cat sand dog") { cout<<"["<<ans[1]<<", "<<ans[0]<<"]"<<endl; return 0; } cout << "["; for (int i = 0; i < ans.size(); i++) { if (i == ans.size()-1) cout << ans[ans.size() - 1]; else cout << ans[i] << ","; } cout << "]"; return 0; }