传送门:UVA-1597
用了一波允许key出现重复的multimap。当一篇文章中出现不止一个关键字时lower_bound用来找第一次出现的位置。
AC代码:
#include<iostream>
#include<map>
#include<vector>
#include<algorithm>
#include<set>
#include<sstream>
using namespace std;
int main()
{
int n;
cin>>n;
vector<string> pq[110];//存文章
multimap<string,int> op[110];//string代表单词,int代表行位置
getchar();//防止读入空串,因为输入n后跟一个换行
for(int i=0;i<n;++i){
string tmp;
while(getline(cin,tmp)){
if(tmp=="**********") break;
pq[i].push_back(tmp);
for(int j=0;j<tmp.size();++j){
if(isalpha(tmp[j])) tmp[j]=tolower(tmp[j]);//存储时应统一大小写
else tmp[j]=' ';
}
stringstream ss(tmp);
string yu;
while(ss>>yu) op[i].insert(make_pair(yu,pq[i].size()-1));
}
}
int m;
cin>>m;
getchar();
while(m--){
string tmp,yu;//暂存指令
getline(cin,tmp);
for(int i=0;i<tmp.size();++i) if(isalpha(tmp[i])) tmp[i]=tolower(tmp[i]);
vector<string> gh;//存指令中的单词
stringstream ss(tmp);
while(ss>>yu) gh.push_back(yu);
if(gh.size()==1||gh.size()==3){
int cnt=0,fg=1;
if(gh.size()==3&&gh[1]=="or") fg=0;//fg用来标识OR情况
if(gh.size()==3) gh.erase(gh.begin()+1,gh.begin()+2);
for(int i=0;i<n;++i){
int flag=1;
if(fg){for(int j=0;j<gh.size();++j) if(!op[i].count(gh[j])){flag=0;break;}}
else{
flag=0;
for(int j=0;j<gh.size();++j) if(op[i].count(gh[j])){flag=1;break;}
}
if(flag){
if(cnt++) cout<<"----------\n";
vector<int> hj;
for(int j=0;j<gh.size();++j){
if(!op[i].count(gh[j])) continue;
multimap<string,int>::iterator it=op[i].lower_bound(gh[j]);//找到第一个出现该单词的地方
for(;it!=op[i].end()&&it->first==gh[j];++it)
hj.push_back(it->second);
}
sort(hj.begin(),hj.end());
int last=-1;//用来筛重复的行(unique没用好。。。)
for(int j=0;j<hj.size();++j){
if(hj[j]!=last) cout<<pq[i][hj[j]]<<endl;
last=hj[j];
}
}
}
if(!cnt) cout<<"Sorry, I found nothing.\n";
cout<<"==========\n";
}
else{//处理NOT term的情况
int cnt=0;
for(int i=0;i<n;++i){
if(op[i].count(gh[1])) continue;
if(cnt++) cout<<"----------\n";
for(int j=0;j<pq[i].size();++j)
cout<<pq[i][j]<<endl;
}
if(!cnt) cout<<"Sorry, I found nothing.\n";
cout<<"==========\n";
}
}
return 0;
}