CCP-CSP认证考试 201809-3 元素选择器 c/c++题解

CCF-CSP认证考试题解目录By东瓜lqd

题目描述:

题解

先说一句,这道题目只拿到了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;
}

发布了197 篇原创文章 · 获赞 18 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_41708792/article/details/103265022