We use cookies to ensure you have the best browsing experience on our website. Please read our cookie policy for more information about how we use cookies.
memory management could be improved but this solution works
#include<cmath>#include<vector>#include<iostream>#include<algorithm>#include<cstdio> // For freopen#include<map>usingnamespacestd;classNode{public:stringdata;vector<Node*>children;voidadd_child(Node*node);boolhas_child(conststringtag_name);Node*get_prev(Node*node);Node*get_next(Node*node);Node*get_last(Node*node);Node*get_node(intindex);boolremove_node(conststring&data);// ConstructorNode(conststd::string&value):data(value){}// Deep copy constructorNode(constNode&other){data=other.data;// Recursively copy all childrenfor(Node*child:other.children){children.push_back(newNode(*child));// Deep copy}}};boolNode::has_child(conststringtag_name){for(Node*child:children){if(child->data==tag_name){returntrue;// Child with the specified data found}}returnfalse;// No child with the specified data found}voidNode::add_child(Node*node){children.push_back(node);}Node*Node::get_last(Node*node){returnchildren[children.size()-1];}Node*Node::get_node(intindex){if(index>=0&&static_cast<size_t>(index)<children.size()){returnchildren[index];}returnnullptr;// Return nullptr if index is out of bounds}Node*Node::get_prev(Node*node){Node*prev_child=nullptr;Node*current_child=nullptr;for(Node*child:children){prev_child=current_child;if(node->data==child->data){current_child=node;}}returnprev_child;}Node*Node::get_next(Node*node){Node*next_child=nullptr;Node*current_child=nullptr;inti=0;for(Node*child:children){if(node->data==child->data){current_child=node;if(children.size()>i){next_child=children[i+1];}}i++;}returnnext_child;}boolNode::remove_node(conststring&data){// Iterate through the list of childrenfor(autoit=children.begin();it!=children.end();++it){if((*it)->data==data){// Remove the node if data matchesdelete*it;// Free memorychildren.erase(it);// Erase the node from the vectorreturntrue;// Node removed successfully}}returnfalse;// Node not found}classHRML_Parser{private:vector<Node*>node_tree;// contains all vectors of tagsmap<string,map<string,string>>node_map;Node*root_node=nullptr;private:stringget_tag_name(conststring&node);// map_node_attributessize_tcreate_node_map(stringcurrent_tag,stringnode,size_tstarting_pos);voidremove_character(string&string_to_update,constcharchar_to_remove);boolvalidate_query(conststring&query);vector<string>split_string(conststring&str,chardelimiter);public:voidbuild_node_tree(conststring&hrml_node);voidbuild_attribute_map(conststring&hrml_node);voidhandle_queries(conststring&query);};voidHRML_Parser::remove_character(string&string_to_update,constcharchar_to_remove){string_to_update.erase(remove(string_to_update.begin(),string_to_update.end(),char_to_remove),string_to_update.end());}voidHRML_Parser::build_node_tree(conststring&hrml_node){stringtag_name=get_tag_name(hrml_node);Node*current_node=newNode(tag_name);// There is not root node if(root_node==nullptr){root_node=current_node;}else{// if a tag is closed which is not the root tagif(hrml_node.substr(0,2)=="</"&&root_node->data==tag_name){if(node_tree.size()==0){node_tree.push_back(newNode(*root_node));}root_node=nullptr;// the root node is closed, so we null it}elseif(hrml_node.substr(0,2)=="</"&&tag_name==root_node->get_last(current_node)->data){node_tree.push_back(newNode(*root_node));// contains a, broot_node->remove_node(current_node->data);}else{root_node->add_child(current_node);}}}voidHRML_Parser::build_attribute_map(conststring&hrml_node){stringtag_name=get_tag_name(hrml_node);size_tcurrent_end_position=hrml_node.find(" ",0);/** * Loops through all attributes in a specific node */boolnode_parsed_done=false;intattributes_parsed=0;while(node_parsed_done==false){attributes_parsed++;current_end_position=create_node_map(tag_name,hrml_node,current_end_position+1);if(current_end_position==string::npos){node_parsed_done=true;return;}elseif(current_end_position+attributes_parsed>=hrml_node.length()){node_parsed_done=true;}}}voidHRML_Parser::handle_queries(conststring&query){if(query.find('~')==string::npos){cout<<"Invalid query!!"<<endl;return;}if(!validate_query(query)){cout<<"Not Found!"<<endl;return;}size_ttag_start=query.find_last_of('.');size_ttag_end=query.find_first_of("~");if(tag_start==string::npos){// e.g tag1~nametag_start=0;}else{tag_start=tag_start+1;}tag_end=tag_end+1;stringtag=query.substr(tag_start,tag_end-1-tag_start);stringattribute=query.substr(tag_end,query.length());map<string,string>node_map_tag=node_map[tag];autoiter=node_map_tag.find(attribute);if(iter!=node_map_tag.end()){// Key exists, access the valuecout<<iter->second<<endl;}else{// Key does not existcout<<"Not Found!"<<endl;}}stringHRML_Parser::get_tag_name(conststring&hrml_node){stringtag_name;size_ttag_end=hrml_node.find_first_of(" ",0);if(tag_end==string::npos){tag_end=hrml_node.find(">",0);}if(tag_end==string::npos){cerr<<"Cannot parse tag"<<endl;return"";}tag_end=tag_end-1;tag_name=hrml_node.substr(0,2)=="</"?hrml_node.substr(2,tag_end):hrml_node.substr(1,tag_end);remove_character(tag_name,'>');remove_character(tag_name,' ');returntag_name;}size_tHRML_Parser::create_node_map(stringcurrent_tag,stringnode,size_tstarting_pos){size_tequal_sign_pos=node.find("=",starting_pos);if(equal_sign_pos==string::npos){returnstring::npos;}stringattribute_name=node.substr(starting_pos,equal_sign_pos-starting_pos);// anothersize_tquote_start_pos=node.find('"',equal_sign_pos);size_tquote_end_pos=node.find('"',quote_start_pos+1);if(quote_start_pos==string::npos||quote_end_pos==string::npos){returnstring::npos;}quote_start_pos=quote_start_pos+1;stringattribute_value=node.substr(quote_start_pos,quote_end_pos-quote_start_pos);// fooremove_character(attribute_name,' ');remove_character(attribute_value,'"');node_map[current_tag][attribute_name]=attribute_value;returnquote_end_pos;}boolHRML_Parser::validate_query(conststring&query){size_ttag_start=query.find('.');size_ttag_end=query.find_first_of("~");vector<string>tags;stringcurrent_tag;// this can be put into a method - get tags from queryif(tag_start==string::npos){// e.g tag1~nametag_start=0;current_tag=query.substr(tag_start,tag_end);tags.push_back(current_tag);}else{// a.c.d.e~strengthtag_start=0;current_tag=query.substr(tag_start,tag_end);tags=split_string(current_tag,'.');}for(Node*node:node_tree){if(node->data==tags[0]){intindex=0;for(stringtag:tags){// skip first tag if(tag!=tags[0]){if(node->get_node(index-1)==nullptr||node->get_node(index-1)->data!=tag){break;}}index++;// all tags found !if(index==tags.size()){returntrue;}}}}returnfalse;}vector<string>HRML_Parser::split_string(conststring&str,chardelimiter){vector<string>result;stringtemp="";for(charch:str){if(ch==delimiter){if(!temp.empty()){result.push_back(temp);// Add substring to the resulttemp="";// Reset temp string}}else{temp+=ch;// Build the substring}}// Add the last substring (if any)if(!temp.empty()){result.push_back(temp);}returnresult;}intmain(){intlines,queries;cin>>lines>>queries;cin.ignore();HRML_Parserparser;stringhrml_node;stringquery_request;for(inti=0;i<lines;++i){getline(cin,hrml_node);parser.build_node_tree(hrml_node);parser.build_attribute_map(hrml_node);}for(inti=0;i<queries;i++){getline(cin,query_request);parser.handle_queries(query_request);}return0;}
Cookie support is required to access HackerRank
Seems like cookies are disabled on this browser, please enable them to open this website
Attribute Parser
You are viewing a single comment's thread. Return to all comments →
memory management could be improved but this solution works