题目描述:
题解:
先说一句,这道题目只拿到了70分,而且具体哪几个点还没有拿到我自己都是知道了,下面是分析过程:
1. 对于数据的输入: 我使用的是vector arr[MAX],也就是一个存储字符串的二维数组。
注意点:因为一行中有多个字符串,多个字符串以空格分隔开来,所以使用getline来输入,然后使用strtok()将每个字符串存入二维数组即可(如果看不懂怎么分割的,请评论)。
2. 注意题目的要求:标签的字母不区分大小写,所以全部转换为小写,id属性的字母区分大小写,所以不要变。
3. 开始元素的选择,也就是输出结果:
我的第一份代码,考虑了:
1.结构化文档只有一级(也就是没有空格)
2.元素选择器只有标签orID属性,不存在后代(也就是每一行只有一个字符串)
所以正好就过了第一个点,10分。
我的第二份代码,考虑了:
1.结构化文档有多级(比较的时候,去掉空格比较)
2.元素选择器只有标签or属性,不存在后代(也就是每一行只有一个字符串)
正好可以过五个点,50分
我的第三份代码,考虑了:
1.结构化文档有多级(比较的时候,去掉空格比较)
2.元素选择器除了有标签or属性以外,还有后代(也就是每一行有多个字符串),但是我只考虑了两代(也就是两个字符串)
按道理来说可以过八个点,但是不知道哪出错了,只有70分。
还可以继续优化的情况(不想继续写了):
1.元素选择器两级的情况应该要都过,80分
2.元素选择器三级or多级的情况也要考虑进来,100分
(我下面贴出的代码,就是由我一层层优化过来的,也就是这个70分代码)
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cstring>
#include <string>
#include <algorithm>
#include <vector>
#include <deque>
#include <list>
#include <utility>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <bitset>
#include <iterator>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int PI = acos(-1);
const int E = exp(1);
const int MOD = 1e9+7;
const int MAX = 1e5+5;
int n,m;
vector <string> text[100+5];// html文档
vector <string> select[10+5];// css选择器
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
/* 输入:n行的结构化文档 + m行的选择器 */
cin >> n >> m;
cin.get();
string str;
for(int i = 0; i < n; i++)
{
getline(cin,str);
char * cStr = (char*)str.c_str();
char * result = NULL;
result = strtok(cStr," ");
while(result != NULL)
{
string tmp = result;
text[i].push_back(tmp);
result = strtok(NULL," ");
}
}
for(int i = 0; i < m; i++)
{
getline(cin,str);
char * cStr = (char*)str.c_str();
char * result = NULL;
result = strtok(cStr," ");
while(result != NULL)
{
string tmp = result;
select[i].push_back(tmp);
result = strtok(NULL," ");
}
}
/* 标签中的字母不看大小写,全变为小写形式\id属性的字母看大小写,还是保留原样
*/
for(int i = 0; i < n; i++)
{
for(int j = 0; j < (int)text[i].size(); j++)
{
//cout << text[i][j] << " ";
if(text[i][j][0] != '#')
{
// 标签对大小写不敏感,如果为字母,则全转换为小写
for(int k = 0; k < (int)text[i][j].length(); k++)
{
if(isalpha(text[i][j][k]))
{
text[i][j][k] = tolower(text[i][j][k]);
}
}
}
else
{
// id属性对大小写敏感,不需要改
}
}
//cout << endl;
}
for(int i = 0; i < m; i++)
{
for(int j = 0; j < (int)select[i].size(); j++)
{
//cout << select[i][j] << " ";
if(select[i][j][0] != '#')
{
// 标签对大小写不敏感,如果为字母,则全转换为小写
for(int k = 0; k < (int)select[i][j].length(); k++)
{
if(isalpha(select[i][j][k]))
{
select[i][j][k] = tolower(select[i][j][k]);
}
}
}
else
{
// id属性对大小写敏感,不需要改
}
}
//cout << endl;
}
/* 输出:m行选择的结果:选择出的元素个数 + 每个元素出现的行号(从小到大排序) */
for(int i = 0; i < m; i++)
{
int sum = 0;
vector <int> res;
if(select[i].size() == 1)// 没有后代关系,就只有一个字符串
{
string Select = select[i][0];
for(int j = 0; j < n; j++)
{
bool flag = false;
for(int k = 0; k < (int)text[j].size(); k++)
{
int index = 0;
while(text[j][k][index] == '.')
{
index++;
}
string tmp = text[j][k].substr(index);
if(tmp == Select)// 比较两个字符串,忽略掉元素选择器的"."
{
flag = true;
res.push_back(j+1);
break;
}
}
if(flag)
{
sum++;
}
}
cout << sum << " ";
for(int j = 0; j < (int)res.size(); j++)
{
cout << res[j] << " ";
}
cout << endl;
}
else if(select[i].size() == 2)// 有后代关系,两个字符串
{
string Select1 = select[i][0];
string Select2 = select[i][1];
for(int j = 0; j < n; j++)
{
bool flag = false;
for(int k = 0; k < (int)text[j].size(); k++)
{
int index = 0;
while(text[j][k][index] == '.')
{
index++;
}
string tmp = text[j][k].substr(index);
if(tmp == Select2)// 比较两个字符串,忽略掉元素选择器的"."
{
/*
flag = true;
res.push_back(j+1);
break;
*/
// 有Select2,还要保证前面有Select1作为祖先,也就是点的个数比Select2的少偶数个
// Select2前面的点有index个
for(int j2 = j-1; j2 >= 0; j2--)
{
for(int k2 = 0; k2 < (int)text[j2].size(); k2++)
{
int index_t = 0;// 记录下Select1前面的点
while(text[j2][k2][index_t] == '.')
{
index_t++;
}
string tmp2 = text[j2][k2].substr(index_t);
if(tmp2 == Select1 && index_t < index)
{
flag = true;
res.push_back(j+1);
break;
}
}
if(flag)
{
break;
}
}
}
}
if(flag)
{
sum++;
}
}
cout << sum << " ";
for(int j = 0; j < (int)res.size(); j++)
{
cout << res[j] << " ";
}
cout << endl;
}
}
return 0;
}