stl应用。爆搜虽然能过,但是其实可以根据词建一个索引,我用了pair<int, int>来代表词出现在第几篇文章的第几行。这样做有个好处就是,把pair<int, int>丢进set,自动就按照文章-行的顺序排好了。接下来只要判断然后构建符合条件的文章set<int>就好(判断成功时顺便),可以用algorithm的交集并集,不过我没用。能改进的地方其实挺多的,不过这样就100ms水进Leaderboard前十了,因垂丝汀。以及sstream真的好慢,去掉直接快20ms……
#include <iostream>
#include <map>
#include <vector>
#include <set>
using namespace std;
map<string, vector<pair<int, int>>> dict;
vector<vector<string>> passages;
int main() {
int n, cur, cnt = 0;
string line, word, key;
cin >> n; getline(cin, line);
cur = 0;
passages.push_back(vector<string>());
while (n) {
getline(cin, line);
if (line[0] == '*' && line.size() == 10) {
if (++cur == n) break;
else {
cnt = 0;
passages.push_back(vector<string>());
}
continue;
}
word.clear(); line.push_back('\n');
for (char c: line) {
if ('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z') {
word.push_back(tolower(c));
} else if (word.size() > 0) {
pair<int, int> term;
if (dict.count(word) == 0)
dict[word] = vector<pair<int, int>>();
term.first = cur; term.second = cnt;
dict[word].push_back(term);
word.clear();
}
}
cnt++;
passages[cur].push_back(line);
}
cin >> n; getline(cin, line);
vector<string> expr;
bool hit = false;
set<int> found;
set<pair<int, int>> lines;
while (n--) {
getline(cin, line);
expr.clear(); hit = false; found.clear(); lines.clear();
int ls = 0, i = 0;
while(++i <= line.size())
if (i == line.size() || line[i] == ' ')
expr.push_back(line.substr(ls, i)), ls = i + 1;
key = expr.size() == 2? expr[1]: expr[0];
if (dict.count(key) > 0) {
for (auto p: dict[key]) {
found.insert(p.first);
lines.insert(p);
}
}
if (expr.size() == 2) {
for (int i = 0; i < passages.size(); i++) {
if (found.count(i) > 0) continue;
if (hit) cout << "----------\n";
for (auto l: passages[i]) cout << l;
hit = true;
}
} else {
if (expr.size() == 3) {
if (expr[1][0] == 'A') {
set<int> nfound;
if (dict.count(expr[2]) > 0) {
for (auto p: dict[expr[2]])
if (found.count(p.first) > 0) {
nfound.insert(p.first);
lines.insert(p);
}
}
found = nfound;
} else {
if (dict.count(expr[2]) > 0) {
for (auto p: dict[expr[2]]) {
found.insert(p.first);
lines.insert(p);
}
}
}
}
if (found.size() > 0) {
int last = 0;
for (auto p: lines) {
if (found.count(p.first) == 0) continue;
if (hit && p.first != last) cout << "----------\n";
cout << passages[p.first][p.second];
hit = true; last = p.first;
}
}
}
if (!hit) cout << "Sorry, I found nothing.\n";
cout << "==========\n";
}
return 0;
}