程序设计思维月模拟 - 元素选择器

T2 - 消消乐大师——Q老师

题目在这里插入图片描述在这里插入图片描述
Input
在这里插入图片描述
Output
在这里插入图片描述
Sample Input
在这里插入图片描述
Sample Output

在这里插入图片描述其他
在这里插入图片描述
解题思路

这是一道比较复杂的模拟题。

首先,输入具有两部分,一部分是文档内容,另一部分是待查询的选择器。这两部分都需要进行一定的处理。

对于文档内容部分,显然需要将其组织成一棵树的结构。
我们需要判断每个位置‘…’的个数来判断是哪一层。有下面几种情况:

  1. 如果是和目前所在的层一样,那就是当前层的兄弟节点,应该被连接到同一个父亲
  2. 如果是当前层的下一层,应该连接为当前层的儿子
  3. 如果是当前层前面的,就需要退回到上面的层进行处理

通过这三种情况,我们可以讲整个文档内容组织成一个树的结构,方便后续的查询和处理。

对于待查询的选择器部分,每个选择器都含有多个元素,所以对于每个选择器我们都应该进行处理。

我们将每个选择器的所有内容进行分割, 并存储在一起(在存储的时候标记是什么类型的)。
之后,开始在树中进行搜索。这里使用的方法是使用深度优先搜索,搜索时在树中依次查询,从上往下,层数小的优先进行匹配。重复这个过程直到查询结束。

完整代码

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
struct node;
struct link
{
	link* next;
	int hs;
};
struct node
{
	int hs;
	int pa;
	string ys;
	string id;
	
	link* cld;
	link* tail;
	int cnt;
	
	void add(int i)
	{
		link* p=new link;
		p->hs=i;
		p->next=NULL;
		if(cnt==0)
		{
			cld=p;
			tail=p;
		}
		else
		{
			tail->next=p;
			tail=p;
		}
		cnt++;
	}
}; 
struct ops
{
	int kd;
	string tag; 
};
ops C;
vector<ops> V;
vector<int> vec_p;
node tree_[105];
string str;
int n,m,v_cnt,ff_n,vec_p_cnt,now_,cc;
void dfs(int i)
{
	if(V[ff_n].kd==0)
	{
		if(tree_[i].ys==V[ff_n].tag)
		{
			if(ff_n==v_cnt-1)
			{
				vec_p.push_back(i);
				link* p=tree_[i].cld;
				while(p!=NULL)
				{
					dfs(p->hs);
					p=p->next;
				}
			}else{
				link* p=tree_[i].cld;
				while(p!=NULL)
				{
					ff_n++;
					dfs(p->hs);
					ff_n--;
					p=p->next;
				}
			}
		}
		else
		{
			link* p=tree_[i].cld;
			while(p!=NULL)
			{
				dfs(p->hs);
				p=p->next;
			}
		} 
	}
	else
	{
		if(tree_[i].id==V[ff_n].tag)
		{
			if(ff_n==v_cnt-1)
			{
				vec_p.push_back(i);
				link* p=tree_[i].cld;
				while(p!=NULL)
				{
					dfs(p->hs);
					p=p->next;
				}
			}
			else
			{
				link* p=tree_[i].cld;
				while(p!=NULL)
				{
					ff_n++;
					dfs(p->hs);
					ff_n--;
					p=p->next;
				}
			}
		}
		else
		{ 
			link* p=tree_[i].cld;
			while(p!=NULL)
			{
				dfs(p->hs);
				p=p->next;
			}
		} 
	} 
}
int main()
{
	cin>>n>>m;
	cin.get();
	now_=-1;
	cc=-1;
	for(int i=1;i<=n;i++)
	{
		getline(cin,str);
		int len=str.length(), c_cnt=0;
		int p;
		for(p=0;p<len;p=p+2)
		{
			if(str[p]=='.'&&str[p+1]=='.')
				c_cnt++;
			else 
				break;
		}
		 
		char ys[85], hs[85];
		int cc_1,cc_2;
		cc_1=cc_2=0;
		for(;p<len;p++)
		{
			if(str[p]!=' ')
			{
				if(str[p]>='A'&&str[p]<='Z')
					str[p]=str[p]+32;
				ys[cc_1++]=str[p];
			}
			else break;
		}
		string st_ys(ys,ys+cc_1);
		
		for(;p<len;p++)
		{
			if(str[p]==' '||str[p]=='#')
				continue;
			else 
				hs[cc_2++]=str[p];
		}
		string st_hs(hs,hs+cc_2);
		
		tree_[i].hs=i;
		tree_[i].ys=st_ys;
		tree_[i].id=st_hs;
		
		if(c_cnt>cc)
		{
			if(now_==-1)
			{
				tree_[1].pa=-1;
			}
			else 
			{
				tree_[now_].add(i);
				tree_[i].pa=now_;
			}
			now_=i;
			cc=c_cnt;
		}
		else if(c_cnt==cc)
		{
			tree_[tree_[now_].pa].add(i);
			tree_[i].pa=tree_[now_].pa;
			now_=i;
		}
		else if(c_cnt<cc)
		{
			while(c_cnt<cc)
			{
				now_=tree_[now_].pa;
				cc--;
			}
			tree_[tree_[now_].pa].add(i);
			tree_[i].pa=tree_[now_].pa;
			now_=i;
		}
	}
	
	for(int i=1;i<=m;i++)
	{
		V.clear();
		vec_p.clear();
		getline(cin,str);
		char st_ss[85];
		int cntS=0,rcdP=0;
		C.tag="";
		if(str[0]=='#')
		{
			C.kd=1;
		}
		else
		{
			C.kd=0;
			if(str[0]>='A'&&str[0]<='Z')str[0]=str[0]+32;
			st_ss[cntS++]=str[0];
		} 
		for(int j=1;j<str.length();j++)
		{
			if(str[j]==' ')
			{
				string str2(st_ss+rcdP,st_ss+cntS);
				C.tag=str2;
				V.push_back(C);
				
				rcdP=cntS;
				j++;
				if(str[j]=='#')
				{
					C.kd=1;
				}
				else
				{
					C.kd=0;
					if(str[j]>='A'&&str[j]<='Z')
						str[j]=str[j]+32;
					st_ss[cntS++]=str[j];
				}
			}
			else 
			{
				if(C.kd==0&&str[j]>='A'&&str[j]<='Z')
					str[j]=str[j]+32;
				st_ss[cntS++]=str[j];
			}
		}
		string str2(st_ss+rcdP,st_ss+cntS);
		C.tag=str2;
		V.push_back(C);
		v_cnt=V.size();
		ff_n=0; 
		dfs(1); 
		cout<<vec_p.size();
		for(int i=0;i<vec_p.size();i++)cout<<" "<<vec_p[i];
		cout<<endl;
	} 
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值