[csp-201809-3]元素选择器-编译原理

声明:同样是参考照抄hyh学长的代码!(有问题我马上删这篇emm

题目链接:http://118.190.20.162/view.page?gpid=T77

题面:

 

这棵树的样子(同样是来自学长的图) 

 

 

题解:

 

要解决的两个关键问题:

第一个是语义解析,也就是把树构造出来。这个也是用指针实现。这个树的构建比起上一题来更简单,因为节点实际上都是一样的,而上一题(JSON查询)则要分为对象和字符串两种。

  这里要注意parent的指向,用一个堆实现查找parent。

第二个是查询。要查询符合条件的路径。这里稍微需要一些思路。

  如果直接从上往下找,那这个复杂度最坏的情况是n^2的。但是在实际情况中(也是题目给的提示),从后往前找会大大减少情况(可以排除很多情况)。

处理细节很重要呀!同样也要想清楚每个函数的作用!

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 
  4 struct tree
  5 {
  6     int id, dots;
  7     string tag, name;
  8     tree* parent;
  9     
 10     tree(int id, int dots, string tag, string name): id(id), dots(dots), tag(tag), name(name) ,parent(0) {}//parent的初始化
 11 };
 12 
 13 void split(const string &str, vector<string> &out)
 14 {
 15     string last;
 16     last.clear();
 17     for (int i = 0; i < str.size(); i++)
 18     {
 19         if(str[i] == ' ') 
 20         {
 21             out.push_back(last);
 22             last.clear();
 23         }
 24         else last+=str[i];
 25     }
 26     out.push_back(last);
 27 }
 28 
 29 bool equal_ignore_case(const string &a,const string &b)
 30 {
 31     if(a.size() != b.size()) return 0;
 32     for(int i = 0; i < a.size(); i++)
 33     {
 34         if(tolower(a[i]) != tolower(b[i])) return 0;
 35     }
 36     return 1;
 37 }
 38 
 39 bool apply(string str, tree *t)
 40 {
 41     if(str[0] == '#') return str == t->name;
 42     else return equal_ignore_case(str, t->tag);
 43 }
 44 
 45 int main()
 46 {
 47     // freopen("a.in","r",stdin);
 48     int n,m;
 49     string line;
 50     scanf("%d%d",&n,&m);
 51     
 52     getline(cin,line);
 53     
 54     vector<tree *> nodes;
 55     stack<tree *> sta;
 56     
 57     for(int i = 1; i <= n; i++)
 58     {
 59         getline(cin, line);
 60         
 61         int dots=0;
 62         while (line[dots] == '.') dots++;
 63         
 64         string tag, name;
 65         stringstream ss(line.substr(dots));
 66         ss >> tag >> name;
 67         
 68         tree *now = new tree(i, dots, tag, name);
 69         if(!sta.empty())
 70         {
 71             tree* top;
 72             while (top = sta.top(), top->dots >= dots) 
 73                 sta.pop();
 74             now->parent = top;
 75         }
 76         sta.push(now);
 77         nodes.push_back(now);
 78     }
 79     /*
 80     for(int i = 0; i < nodes.size(); i++)
 81     {
 82         printf("id = %d  dots = %d ",nodes[i]->id,nodes[i]->dots);
 83         cout << "tag = " << nodes[i]->tag << " name = " << nodes[i]->name ;
 84         if(nodes[i]->parent) cout << " parent = " << nodes[i]->parent->id << endl;
 85         else cout << endl;
 86     }
 87     */
 88     vector<string> selector;
 89     vector<int> ans;
 90     ans.clear();
 91     while (m--)
 92     {
 93         getline(cin, line);
 94         selector.clear();
 95         split(line, selector);
 96         // printf("************* m = %d\n",m);
 97         // for(int i = 0 ; i < selector.size(); i++) 
 98             // cout << selector[i] << endl;
 99         ans.clear();
100         for (int i = 0; i < nodes.size(); i++)
101         {
102             if (apply(selector.back(),nodes[i]))
103             {
104                 tree *t = nodes[i];
105                 int sl = selector.size()-1;
106                 while(t && sl>=0)
107                 {
108                     if(apply(selector[sl],t)) sl--;
109                     t = t->parent;
110 
111                 }
112                 if (sl == -1) 
113                     ans.push_back(nodes[i]->id);
114             }
115         }
116         printf("%d ",ans.size()); 
117         for (int i = 0; i < ans.size() ; i++)
118             printf("%d ",ans[i]);
119         printf("\n");
120     }
121     
122     return 0;
123 }

 更新一下代码(刷题的时候又遇到了这题,重新做了一遍(并没有什么区别..写码习惯不同))

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 
  4 struct tree{
  5     string tag,name;
  6     int dots;
  7     tree* parent;
  8     
  9     tree(int dots, string tag, string name): dots(dots),tag(tag),name(name),parent(0) {}
 10 };
 11 
 12 bool check(const string &s,tree* t)
 13 {
 14     if(s[0]=='#') return s == t->name;
 15     else 
 16     {
 17         if(s.size()!=t->tag.size()) return 0;
 18         for(int i=0;i<s.size();i++)
 19         {
 20             if(tolower(s[i])!=tolower(t->tag[i])) return 0;
 21         }
 22         return 1;
 23     }
 24 }
 25 
 26 void divide(const string &s,vector<string> &vec)
 27 {
 28     string token;
 29     token.clear();
 30     vec.clear();
 31     for(int i=0;i<s.size();i++)
 32     {
 33         if(s[i]==' ') 
 34         {
 35             vec.push_back(token);
 36             token.clear();
 37         }
 38         else token+=s[i];
 39     }
 40     vec.push_back(token);
 41 }
 42 
 43 int main()
 44 {
 45     //freopen("a.in","r",stdin);
 46     int n,m;
 47     scanf("%d%d",&n,&m);
 48     string line;
 49     getline(cin,line);
 50     
 51     vector<tree* > nodes;
 52     nodes.clear();
 53     stack<tree* > sta;
 54     while(!sta.empty()) sta.pop();
 55     
 56     for(int i=1;i<=n;i++)
 57     {
 58         getline(cin,line);
 59         
 60         int dots=0;
 61         while(line[dots]=='.') dots++;
 62         
 63         string tag,name;
 64         stringstream ss(line.substr(dots));
 65         ss >> tag >> name;
 66         
 67         tree* now = new tree(dots, tag, name);
 68         
 69         if(!sta.empty())
 70         {
 71             tree* top;
 72             while( top = sta.top() , top->dots >= dots ) 
 73                 sta.pop();  
 74             now->parent = top;
 75         }
 76         sta.push(now);
 77         nodes.push_back(now);
 78     }
 79     
 80     // for(int i=0;i<nodes.size();i++)
 81     // {
 82         // cout << "id = " << i << " tag = " << nodes[i]->tag << " name = " << nodes[i]->name ;
 83         // if(nodes[i]->parent) cout<< " parent = " << nodes[i]->parent->tag;
 84         // cout << endl;
 85     // }
 86         
 87     vector<string> sel;
 88     vector<int> ans;
 89     
 90     while(m--)
 91     {
 92         getline(cin,line);
 93         divide(line,sel);
 94         
 95         ans.clear();
 96         
 97         for(int i=0;i<nodes.size();i++)
 98         {
 99             int sl=sel.size()-1;
100             if(check(sel[sl],nodes[i])) 
101             {
102                 tree* t=nodes[i]->parent;
103                 sl--;
104                 while(t && sl>=0)
105                 {
106                     if(check(sel[sl],t)) sl--;
107                     t=t->parent;
108                 }
109                 if(sl==-1) ans.push_back(i+1);
110             }
111         }
112         printf("%d ",ans.size());
113         for(int i=0;i<ans.size();i++) printf("%d ",ans[i]);printf("\n");
114     }
115     return 0;
116 }

 

posted @ 2018-11-22 09:43  拦路雨偏似雪花  阅读(1136)  评论(0编辑  收藏  举报