您的位置:首页 > 其它

UVA ~ 1597 ~ Searching the Web (模拟,map+bitset)

2018-01-14 18:45 369 查看
题意:输入n篇文章和m个请求(n < 100, m≤50000),每个请求都是以下四种格式之一。

1.A:查找包含关键字A的文章。(即如果某篇文章中含有A,输出含有A的行)

2.A AND B:查找同时包含关键字A和B的文章。(即如果某篇文章中含有A和B,输出含有A的行,或含有B的行)

3.A OR B:查找包含关键字A或B的文章。(即如果某篇文章中含有A或B,输出含有A的行,或含有B的行)

4.NOT A:查找不包含关键字A的文章。(即
4000
如果某篇文章不含有A,输出整篇文章)

关键字只有小写字母组成,查找时忽略大小写。每行不超过80个字符,一共不超过1500行。

思路:vector一行一行保存原文,limit[i]保存第i篇文章在哪一行之前,用map<string, bitset<1050> >表示某个单词word,在那些行中出现过。输出比较麻烦,我们先把所有行的输出状态的处理到一个out中,然后在输出。输出的时候立两个flag,has_out表示之前是否有输出,need_out表示该篇文章是否需要输出。

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1505;
int n, m;
vector<string> Article;//文章
map<string, bitset<MAXN> > M;//单词在第几行
int limit[105] = {0}; //第i篇文章在第几行之前
void Insert(string str,int row)
{
for (auto &i: str)//字母转化为小写,符号化为空格
{
if (isalpha(i)) i = tolower(i);
else i = ' ';
}
stringstream ss(str);
string word;
while (ss >> word) M[word].set(row, 1);//单词出现的行设置为1
}
int main()
{
//ofstream cout("out.txt");
string str;
cin >> n; cin.get();//读取回车
int row = 0;
for (int i = 1; i <= n; i++)
{
while (getline(cin, str) && str != "**********")
{
Article.push_back(str);//保存原文
Insert(str, row);//处理这一行
row++;//第row行
}
limit[i] = row;
}
cin >> m; cin.get();//读取回车
while (m--)//m次操作
{
getline(cin, str);
bitset<MAXN> A, B, out;//关键字A,B对应的行的状态,out为行的输出状态
if (str.find(" AND ") != string::npos)
{
A = M[str.substr(0, str.find(" AND "))], B = M[str.substr(str.find(" AND ") + 5)];
for (int i = 1; i <= n; i++)
{
bool flag1 = false, flag2 = false;//本篇文章中关键字A,B是否出现过
for (int j = limit[i - 1]; j < limit[i]; j++)//本篇文章对应的行
{
if(A[j]) { flag1 = true; }
if(B[j]) { flag2 = true; }
}
if (flag1 && flag2)//关键字A,B都出现过
{
//处理需要输出的行,即A或者B在的行
for (int j = limit[i - 1]; j < limit[i]; j++) out[j] = A[j] || B[j];
}
}
}
else if (str.find(" OR ") != string::npos)
{
A = M[str.substr(0, str.find(" OR "))], B = M[str.substr(str.find(" OR ") + 4)];
for (int i = 1; i <= n; i++)
{
bool flag1 = false, flag2 = false;//本篇文章中关键字A,B是否出现过
for (int j = limit[i - 1]; j < limit[i]; j++)//本篇文章对应的行
{
if(A[j]) { flag1 = true; }
if(B[j]) { flag2 = true; }
}
if (flag1 || flag2)//A出现过或者B出现过
{
//处理需要输出的行,即A或者B在的行
for (int j = limit[i - 1]; j < limit[i]; j++) out[j] = A[j] || B[j];
}
}
}
else if (str.find("NOT ") != string::npos)
{
A = M[str.substr(str.find("NOT ") + 4)];
for (int i = 1; i <= n; i++)
{
bool flag1 = false;
for (int j = limit[i - 1]; j < limit[i]; j++)//第i篇文章对应的行
{
if(A[j]) { flag1 = true; }
}
if (!flag1)//本篇文章没出现过
{
//处理需要输出的行,即本篇文章对应所有的行
for (int j = limit[i - 1]; j < limit[i]; j++) out[j] = true;
}
}
}
else { out = M[str]; }//关键字A所在的行即要输出的行
//输出
bool has_out = false;//之前有没有输出
for (int i = 1; i <= n; i++)
{
bool need_out = false;//本篇文章是否需要输出
for (int j = limit[i - 1]; j < limit[i]; j++)
{
if (out[j]) { need_out = true; break; }
}
if (need_out)//需要输出
{
if(has_out) cout << "----------" << endl;//如果之前有输出那么就输出一行分割线
for (int j = limit[i - 1]; j < limit[i]; j++)//遍历输出
{
if (out[j]) cout << Article[j] << endl;//需要输出就输出原来的文章
}
has_out = true;
}
}
if (!has_out) cout << "Sorry, I found nothing." << endl;//没有输出
cout << "==========" << endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: