Run Time: 0.100
Ranking (as of 2018-02-05): 24 out of 188
Language: C++
/* UVa 1597 - Searching the Web To build using Visual Studio 2015: cl -EHsc -O2 UVa_1597_Searching_the_Web.cpp */ #include <iostream> #include <string> #include <sstream> #include <map> #include <set> #include <algorithm> #include <iterator> #include <cctype> using namespace std; const int N_max = 100, nr_chars_max = 80, nr_lines_max = 1500; int N, M, nr_lines; string lines[nr_lines_max + 1]; pair<int, int> doc_lines[N_max]; // first is the first line, second is the (last line) + 1 enum {op_NONE, op_AND, op_OR, op_NOT}; map< string, set< pair<int, int> > > inverted_index; // key is a term, value is its buckets const string not_found = "Sorry, I found nothing.\n", separator = "----------\n", terminator = "==========\n"; #ifdef DEBUG void print_inverted_index() { cout << inverted_index.size() << " words\n"; for (map< string, set < pair<int, int> > >::const_iterator i = inverted_index.begin(); i != inverted_index.end(); ++i) { cout << i->first << ':'; for (set < pair<int, int> >::const_iterator j = i->second.begin(); j != i->second.end(); ++j) cout << " (" << j->first << ", " << j->second << ')'; cout << endl; } } #endif void get_docs(set<int>& docs, const string& term) { map< string, set< pair<int, int> > >::const_iterator i = inverted_index.find(term); if (i != inverted_index.end()) for (set< pair<int, int> >::const_iterator j = i->second.begin(); j != i->second.end(); ++j) docs.insert(j->first); } void get_buckets(set< pair <int, int> >& buckets, const string& term) { map< string, set< pair<int, int> > >::const_iterator i = inverted_index.find(term); if (i != inverted_index.end()) { if (buckets.empty()) buckets = i->second; else { for (set< pair<int, int> >::const_iterator j = i->second.begin(); j != i->second.end(); ++j) buckets.insert(*j); } } } void get_buckets(set<int>& docs, set< pair <int, int> >& buckets, const string& term) { map< string, set< pair<int, int> > >::const_iterator i = inverted_index.find(term); if (i != inverted_index.end()) { if (buckets.empty()) { buckets = i->second; for (set< pair<int, int> >::const_iterator j = i->second.begin(); j != i->second.end(); ++j) docs.insert(j->first); } else { for (set< pair<int, int> >::const_iterator j = i->second.begin(); j != i->second.end(); ++j) { docs.insert(j->first); buckets.insert(*j); } } } } void print_lines(const set< pair <int, int> >& buckets) { if (buckets.empty()) cout << not_found; else { set< pair <int, int> >::const_iterator i = buckets.begin(); int j = i->first; cout << lines[i->second] << endl; for (++i ; i != buckets.end(); ++i) { if (i->first != j) { j = i->first; cout << separator; } cout << lines[i->second] << endl; } } } void print_lines(const set<int>& docs, const set< pair <int, int> >& buckets) { if (docs.empty()) cout << not_found; else { int k = docs.size(); set< pair <int, int> >::const_iterator i = buckets.begin(); while (true) { while (i != buckets.end() && docs.find(i->first) == docs.end()) ++i; if (i == buckets.end()) break; int j = i->first; cout << lines[i->second] << endl; for (++i ; i != buckets.end(); ++i) { if (i->first != j) { if (--k) cout << separator; break; } cout << lines[i->second] << endl; } } } } int main() { string s; istringstream iss; getline(cin, s); iss.str(s); iss >> N; iss.clear(); nr_lines = 0; for (int i = 0; i < N; i++) { // read N documents doc_lines[i].first = nr_lines; while (true) { // read one document string& line = lines[nr_lines]; getline(cin, line); if (line == "**********") break; char word[nr_chars_max + 1]; for (const char* p = line.c_str(); *p; ) { if (isalpha(*p)) { char* q = word; *q++ = tolower(*p++); while (isalpha(*p)) *q++ = tolower(*p++); *q = '\0'; inverted_index[word].insert(make_pair(i, nr_lines)); } else p++; } nr_lines++; } doc_lines[i].second = nr_lines; } #ifdef DEBUG print_inverted_index(); #endif getline(cin, s); iss.str(s); iss >> M; iss.clear(); while (M--) { getline(cin, s); iss.str(s); string term1, term2; iss >> term1; int op = op_NONE; if (term1 == "NOT") { op = op_NOT; iss >> term1; } else if (iss >> term2) { op = (term2 == "AND") ? op_AND : op_OR; iss >> term2; } iss.clear(); switch (op) { case op_NONE: // term1 { set< pair <int, int> > buckets; get_buckets(buckets, term1); print_lines(buckets); } break; case op_AND: // term1 AND term2 { set<int> docs, another_docs, and_docs; set< pair <int, int> > buckets; get_buckets(docs, buckets, term1); get_buckets(another_docs, buckets, term2); set_intersection(docs.begin(), docs.end(), another_docs.begin(), another_docs.end(), inserter(and_docs, and_docs.begin())); print_lines(and_docs, buckets); } break; case op_OR: // term1 OR term2 { set< pair <int, int> > buckets; get_buckets(buckets, term1); get_buckets(buckets, term2); print_lines(buckets); } break; case op_NOT: // NOT term1 { set<int> docs; get_docs(docs, term1); int k = N - docs.size(); if (!k) cout << not_found; else { for (int i = 0; i < N; i++) if (docs.find(i) == docs.end()) { for (int j = doc_lines[i].first; j < doc_lines[i].second; j++) cout << lines[j] << endl; if (--k) cout << separator; } } } break; } cout << terminator; } return 0; }
No comments:
Post a Comment