第四次月模拟题-201809-3

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
题目分析:
本题很绕,但是关键的部分非常简洁,实际上就是对应的查找字符而已,只不过复杂一点的是可能会有分级,这样我们就要用一个树结构来储存,首先我们先要定义一个结构题,包含标签、名字。前面的点(因为这些点是要输入的,所以单独处理,而且这些点的数目也能体现所在的层次)还有它的父母(确定是在第几层)。

struct tree
{
	string tag;
	string name;
	int dots;
	tree* parent;
	tree(int dots,string tag,string name):dots(dots),tag(tag),name(name),parent(0){}
};

首先我们确定如何查找对应的序列,那么我们就要看开头是啥,如果是#那就是属性,直接找就可以了。

	if(s[0]=='#')
	{
		if(s==t->name)
		{
			return true;
		}
		else
		{
			return false;
		}
	}

否则就是正常的查找,如果字符串大小不一样肯定不会相等,减少了比较的次数。相等的话就依次比较,注意这里面大小写不敏感,意味着就都得转换为小写或者大写然后比较,只要有一个不相等就false,都相等就true。

		if(s.size()!=t->tag.size())
		{
			return false;
		}
		int ssize=s.size();
		for(int i=0;i<ssize;i++)
		{
			if(tolower(s[i])!=tolower(t->tag[i]))
			{
				return false;
			}
		}
		return true;
	}

然后就是分开这一个一个的单词了,因为输入之间有空格,在编译器里空格表示输入完成,所以我们对于一行多个输入就要用先统一读取一行然后在分开他们的方法,遇到了空格就意味着读取完成,清空继续读取,否则就加入到字符中来。

	int ssize=s.size();
	for(int i=0;i<ssize;i++)
	{
		if(s[i]==' ')
		{
			vec.push_back(token);
			token.clear();
		}
		else
		{
			token+=s[i];
		}
	}
	vec.push_back(token);

为了体现层次性,我们定义一个栈来储存当前是第几层的字符内容,我们前面说了可以数点来判断是第几层。

		int dots=0;
		while(line[dots]=='.')
		{
			dots++;
		}

这样,我们根据点的个数就可以判断栈的层次,只需要找到比点比他小的位置就可以设置为父亲了,层次性就解决了。

		tree* now=new tree(dots,tag,name);
		if(!sta.empty())
		{
			tree* top;
			while(top=sta.top(),top->dots>=dots)
			{
				sta.pop();
			}
			now->parent=top;
		}
		sta.push(now);
		nodes.push_back(now);

之后就是比较环节了。对于每一个结点来说,从最下层最后一个字符依次往前比较,如果对上了就往前字符比较并且往上走,如果比较到头了依然符合要求那就意味着符合要求,此时就可以记录下行数了。

		int nsize=nodes.size();
		for(int i=0;i<nsize;i++)
		{
			int sl=sel.size()-1;
			if(check(sel[sl],nodes[i])==true)
			{
				tree* t=nodes[i]->parent;
				sl--;
				while(t!=0&&sl>=0)
				{
					if(check(sel[sl],t)==true)
					{
						sl--;
					}
					t=t->parent;
				}
				if(sl==-1)
				{
					ans.push_back(i+1);
				}
			}
		}

输出的时候记得带上空格,而且第一个是大小后面的是行数,所以要分开两部分输出,同时输出完毕之后记得换行。

		cout<<ans.size()<<" ";
		int asize=ans.size();
		for(int i=0;i<asize;i++)
		{
			cout<<ans[i]<<" ";
		}
		cout<<endl;

代码如下:

#include<iostream>
#include<cstring>
#include<vector>
#include<stack>
#include<sstream>
using namespace std;
struct tree
{
	string tag;
	string name;
	int dots;
	tree* parent;
	tree(int dots,string tag,string name):dots(dots),tag(tag),name(name),parent(0){}
};
bool check(const string &s,tree *t)
{
	if(s[0]=='#')
	{
		if(s==t->name)
		{
			return true;
		}
		else
		{
			return false;
		}
	}
	else
	{
		if(s.size()!=t->tag.size())
		{
			return false;
		}
		int ssize=s.size();
		for(int i=0;i<ssize;i++)
		{
			if(tolower(s[i])!=tolower(t->tag[i]))
			{
				return false;
			}
		}
		return true;
	}
}
void devide(const string &s,vector<string> &vec)
{
	string token;
	token.clear();
	vec.clear();
	int ssize=s.size();
	for(int i=0;i<ssize;i++)
	{
		if(s[i]==' ')
		{
			vec.push_back(token);
			token.clear();
		}
		else
		{
			token+=s[i];
		}
	}
	vec.push_back(token);
}
int main()
{
	int n,m;
	cin>>n>>m;
	string line;
	getline(cin,line);
	vector<tree*> nodes;
	nodes.clear();
	stack<tree*> sta;
	while(!sta.empty())
	{
		sta.pop();
	}
	for(int i=1;i<=n;i++)
	{
		getline(cin,line);
		int dots=0;
		while(line[dots]=='.')
		{
			dots++;
		}
		string tag,name;
		stringstream ss(line.substr(dots));
		ss>>tag>>name;
		tree* now=new tree(dots,tag,name);
		if(!sta.empty())
		{
			tree* top;
			while(top=sta.top(),top->dots>=dots)
			{
				sta.pop();
			}
			now->parent=top;
		}
		sta.push(now);
		nodes.push_back(now);
	}
	vector<string> sel;
	vector<int> ans;
	while(m--)
	{
		getline(cin,line);
		devide(line,sel);
		ans.clear();
		int nsize=nodes.size();
		for(int i=0;i<nsize;i++)
		{
			int sl=sel.size()-1;
			if(check(sel[sl],nodes[i])==true)
			{
				tree* t=nodes[i]->parent;
				sl--;
				while(t!=0&&sl>=0)
				{
					if(check(sel[sl],t)==true)
					{
						sl--;
					}
					t=t->parent;
				}
				if(sl==-1)
				{
					ans.push_back(i+1);
				}
			}
		}
		cout<<ans.size()<<" ";
		int asize=ans.size();
		for(int i=0;i<asize;i++)
		{
			cout<<ans[i]<<" ";
		}
		cout<<endl;
	}
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值