这道题仍然是做了3个月,一直超时和WA,最后参考某大神的AC代码终于过了。巧妙的地方就是运用||和&&来进行搜索时的“和”和“或”操作,另外分析文章后的存储数据的数据结构也很重要,还有代码中很多重复的地方不妨#define了,可以使代码更加简洁。不过最后AC还是用了1.1秒,貌似有用字典树做的方法会更快吧。
#include <bits/stdc++.h>
using namespace std;
using State = bool[1505];
#define FOR for (int j = limit[i]; j < limit[i + 1]; ++j)
map<string, State> Index;
vector<string> doc;
int limit[128];
void insert(string s, const int no){
doc.push_back(s);
for (auto & i : s){
if (isalpha(i)) i = tolower(i);
else i = ' ';
}
stringstream ss(s); string word;
while (ss >> word)
Index[word][no] = true;
}
int main()
{
ios::sync_with_stdio(false);
int N, cnt = 0; cin >> N; cin.get();
for (int n = 0; n < N; ++n) {
string line;
while (getline(cin, line)){
if (line == "**********"){
limit[n + 1] = cnt;
break;
}
else insert(line, cnt++);
}
}
int M; cin >> M; cin.get();
while (M--){
string cmd; getline(cin, cmd);
bool *A, *B;
State out = {0};
if (cmd[0] == 'N'){
A = Index[cmd.substr(4)];
for (int i = 0; i < N; ++i){
bool flag = true;
FOR if (A[j]) { flag = false; break; }
FOR out[j] = flag;
}
}
else if (cmd.find("AND") != string::npos){
A = Index[cmd.substr(0, cmd.find(" AND "))];
B = Index[cmd.substr(cmd.find(" AND ")+5)];
for (int i = 0; i < N; ++i){
bool flagA = false, flagB = false;
FOR if (A[j]) { flagA = true; break; }
FOR if (B[j]) { flagB = true; break; }
if (flagA && flagB) FOR out[j] = A[j] || B[j];
}
}
else if (cmd.find("OR") != string::npos){
A = Index[cmd.substr(0, cmd.find(" OR "))];
B = Index[cmd.substr(cmd.find(" OR ") + 4)];
for (int i = 0; i < cnt; ++i) out[i] = A[i] || B[i];
}
else memcpy(out, Index[cmd], sizeof(State));
bool has_out = false;
for (int i = 0; i < N; ++i){
bool need_out = false;
FOR if (out[j]) {need_out = true; break;}
if (need_out){
if (has_out) cout << "----------" << endl;
FOR if (out[j]) cout << doc[j] << endl;
has_out = true;
}
}
if (!has_out) cout << "Sorry, I found nothing." << endl;
cout << "==========" << endl;
}
return 0;
}