201809-3 元素选择器


思路

这道题主要还是学一下利用栈来模拟DFS的过程。只需要顺序遍历整个文本,然后对于不是此文本父节点的点弹出栈即可。同样,这个点要匹配的字符串的位置和父节点要匹配的字符串的位置相同。注意一下,如果父节点已经可以匹配了,那么这个节点还是要匹配最后一个字符串。非常牛呀这个思路,YCW YYDS!

代码

#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

int n, m;
vector strs;

struct Node
{
    int tab;
    string tag, id;
    int k;  // 当前节点最多可以匹配到第几个位置

    Node(string str)
    {
        int i = 0;
        while (str[i] == '.') i ++ ;
        tab = i;
        while (i < str.size() && str[i] != ' ')
            tag += tolower(str[i ++ ]);
        i ++ ; // 过滤掉空格
        while (i < str.size()) id += str[i ++ ];
        k = 0;
    }
    bool check(string& word)
    {
        if (word[0] == '#') return word == id;
        return word == tag;
    }
};

void work(vector& ws)
{
    vector res;
    stack stk;
    for (int i = 0; i < strs.size(); i ++ )
    {
        string str = strs[i];
        Node t(str);
        while (stk.size() && stk.top().tab >= t.tab) stk.pop();
        if (stk.size()) t.k = stk.top().k;
        if (t.k == ws.size()) t.k -- ;
        if (t.check(ws[t.k]))
        {
            t.k ++ ;
            if (t.k == ws.size()) res.push_back(i + 1);
        }
        stk.push(t);
    }
    cout << res.size();
    for (auto x: res) cout << ' ' << x;
    cout << endl;
}

int main()
{
    cin >> n >> m;
    getchar();
    string str;
    while (n -- )
    {
        getline(cin, str);
        strs.push_back(str);
    }
    while (m -- )
    {
        getline(cin, str);
        stringstream ssin(str);
        vector ws;
        while (ssin >> str)
        {
            if (str[0] != '#')
                for (auto& c: str)
                    c = tolower(c);
            ws.push_back(str);
        }
        work(ws);
    }
    return 0;
}

作者:yxc
链接:https://www.acwing.com/activity/content/code/content/893996/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
csp