回头有时间再加上注释
#include <bits/stdc++.h>
#include "query_base.h"
using namespace std;
int main(void) {
ifstream in("test.txt");
new_runQueries(in);
return 0;
}
#include <bits/stdc++.h>
#ifndef QUERY_BASE_H
#define QUERY_BASE_H
using namespace std;
class QueryResult;
class TextQuery{
public:
using line_no = vector<string>:: size_type;
TextQuery(ifstream &infile);
QueryResult query(const string &) const;
private:
shared_ptr<vector<string>> file;
map<string, shared_ptr<set<line_no>>> wm;
};
TextQuery::TextQuery(ifstream &infile) : file(new vector<string>){
string text;
while(getline(infile, text)){
file -> push_back(text);
int n = file -> size() - 1;
istringstream line(text);
string word;
while(line >> word){
auto &lines = wm[word];
if (!lines){
lines.reset(new set<line_no>);
}
lines -> insert(n);
}
}
}
class QueryResult{
public:
friend ostream& print(ostream&, const QueryResult&);
using line_no = vector<string>:: size_type;
QueryResult(const shared_ptr<vector<string>> &f,const string &w, const shared_ptr<set<line_no>> &l) :
file(f), word(w), lines(l){}
std::set<TextQuery::line_no>::iterator
begin() { return lines->begin(); }
std::set<TextQuery::line_no>::iterator
end() { return lines->end(); }
shared_ptr<vector<string>> get_file() const {return file;}
void test_lines() {for (auto n : *lines) cout << n << endl;}
private:
shared_ptr<vector<string>> file;
string word;
shared_ptr<set<line_no>> lines;
};
QueryResult TextQuery::query(const string & s) const{
static shared_ptr<set<line_no>> line_empty(new set<line_no>);
if (wm.find(s) == wm.end())
return QueryResult(file, s, line_empty);
return QueryResult(file, s, wm.at(s));
}
ostream& print(ostream& os, const QueryResult& que){
int n = que.lines -> size();
os << "element occurs " << n << " times" << endl;
for (auto num : *que.lines){
os << " (line " << num + 1 << ") " << *(que.file -> begin() + num) << endl;
}
return os;
}
class Query_base{
public:
friend class Query;
protected:
using line_no = TextQuery::line_no;
virtual ~Query_base() = default;
private:
virtual QueryResult eval(const TextQuery &tq) const = 0;
virtual string rep() const = 0;
};
class Query{
public:
friend Query operator~ (const Query&);
friend Query operator| (const Query&, const Query&);
friend Query operator& (const Query&, const Query&);
Query (const string&);
QueryResult eval(const TextQuery&t) const {return q -> eval(t);}
string rep() const {return q -> rep();}
void empty() {q = nullptr;}
private:
Query(shared_ptr<Query_base> query) : q(query) {}
shared_ptr<Query_base> q;
};
ostream& operator<<(ostream &os, const Query &q){
return os << q.rep();
}
class WordQuery : public Query_base{
friend class Query;
WordQuery(const string &s) : query_word(s) {}
QueryResult eval(const TextQuery &tq) const {return tq.query(query_word);}
string rep() const {return query_word;}
string query_word;
};
inline
Query::Query(const string &s) : q(new WordQuery(s)) {}
class NotQuery : public Query_base{
friend class Query;
friend Query operator~ (const Query&);
NotQuery(const Query &q) : query(q) {}
QueryResult eval(const TextQuery &tq) const;
string rep() const {return "~(" + query.rep() + ")";}
Query query;
};
inline
Query operator~ (const Query& ope){
return shared_ptr<Query_base>(new NotQuery(ope));
}
class BinaryQuery : public Query_base{
protected:
BinaryQuery(const Query &l, const Query &r, string s) : lhs(l), rhs(r), op(s) {}
Query lhs, rhs;
string op;
string rep() const {return "(" + lhs.rep() + op + rhs.rep() + ")";}
};
class AndQuery : public BinaryQuery{
friend Query operator& (const Query&, const Query&);
AndQuery(const Query &l, const Query &r) : BinaryQuery(l, r, "&") {}
QueryResult eval(const TextQuery &tq) const;
};
inline
Query operator& (const Query& q1, const Query& q2){
return shared_ptr<Query_base>(new AndQuery(q1, q2));
}
class OrQuery : public BinaryQuery{
friend Query operator| (const Query&, const Query&);
OrQuery(const Query &l, const Query &r) : BinaryQuery(l, r, "|") {}
QueryResult eval(const TextQuery &tq) const;
};
inline
Query operator| (const Query& q1, const Query& q2){
return shared_ptr<Query_base>(new OrQuery(q1, q2));
}
QueryResult OrQuery::eval(const TextQuery &tq) const{
auto right = rhs.eval(tq);
auto left = lhs.eval(tq);
auto ret_lines = make_shared<set<line_no>>(left.begin(), left.end());
ret_lines -> insert(right.begin(), right.end());
return QueryResult(left.get_file(), rep(), ret_lines);
}
QueryResult AndQuery::eval(const TextQuery &tq) const{
auto right = rhs.eval(tq);
auto left = lhs.eval(tq);
auto ret_lines = make_shared<set<line_no>>();
set_intersection(left.begin(), left.end(), right.begin(), right.end(), inserter(*ret_lines, ret_lines -> begin()));
return QueryResult(left.get_file(), rep(), ret_lines);
}
QueryResult NotQuery::eval(const TextQuery &tq) const{
auto result = query.eval(tq);
auto ret_lines = make_shared<set<line_no>>();
auto beg = result.begin(), end = result.end();
auto sz = result.get_file() -> size();
for (int i = 0; i < sz; i++){
if (beg == end || *beg != i)
ret_lines -> insert(i);
else
beg++;
}
return QueryResult(result.get_file(), rep(), ret_lines);
}
void runQueries(ifstream &infile){
TextQuery tq(infile);
while (true){
cout << "enter word to look for" << endl;
string s;
if (!(cin >> s) || s == "_q")
break;
print(cout, tq.query(s)) << endl;
}
}
void new_runQueries(ifstream &infile){
while (true){
infile.clear();
infile.seekg(0);
cout << "enter word to look for" << endl;
string s;
if (!(getline(cin, s)) || s == "_q")
break;
vector<string> words;
istringstream line(s);
string word;
while(line >> word){
words.push_back(word);
}
int n = words.size();
auto q = words[0] == "~" ? ~Query(words[0]) : Query(words[0]);
int i = words[0] == "~" ? : 1;
for (; i < n - 1; i+=2){
if (words[i + 1] != "~"){
if (words[i] == "&"){
q = q & Query(words[i + 1]);
}
else if (words[i] == "|"){
q = q & Query(words[i + 1]);
}
else{
cerr << "error1" << endl;
}
}
else{
if (words[i] == "&"){
q = q & (~Query(words[i + 2]));
}
else if (words[i] == "|"){
q = q | (~Query(words[i + 2]));
}
else{
cerr << "error2" << endl;
}
i++;
}
}
auto ans = q.eval(infile);
print(cout, ans) << endl;
}
}
#endif