这道题仍然是做了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; }