月模拟题:元素选择器

题目大意

在这里插入图片描述
在这里插入图片描述

输入输出

在这里插入图片描述

思路

这个题与之前的文件系统模拟题有些类似,但没有那个那么复杂,这个题主要分为两个步骤:

  1. 建树
    首先根据输入建立树结构,树节点需要包含:标签,id,层级。层级通过’.'个数除2就可以获得,此处没有必要记录树节点之间的父子关系(也就是不用记录边),因为题目的输入就是按照父子关系输入的,按照顺序遍历的过程中,自然可以满足由父到子这一过程。

  2. 选择元素
    对于选标签或者选id,都非常简单,遍历一遍所有的元素即可。
    对于后代选择,不需要区分匹配的是标签还是id,只要有一个能匹配上就可以。 有两种方法,一个是自顶向下,一个是自下而上。自顶向下指的是,贪心的去匹配最早出现的,满足后代选择器中要求的系列元素,例如下例,若要查找div,div,p,则会首先匹配前三行,当全部匹配成功后,依靠接下来的元素的层级数,决定下一轮从选择器的哪个元素开始匹配,如第四行的p元素层级小于(等于也可)最后一个匹配成功位置的层级,则p还是去匹配选择器中的最后一个元素;第五行的div元素层级与最后一次匹配成功的元素的第二个层级相同(第二行的div),所以就会从元素选择器中的第二个开始匹配。

div
..div 
....p
......p
..div

自底向上方法指的是先匹配最后一个元素,然后在层级递减的元素序列里面,匹配祖先,一旦所有选择器中的元素都被匹配,则完成一轮匹配,下一轮匹配的开始位置,是元素序列中下一个与最后一个元素相等的位置。

这两种方法的共同点在于,都需要确保选择器中的元素,处于一个层级递增或递减的序列中,可以借助单调栈来完成这一任务。

代码

自上而下:

#include<bits/stdc++.h>
using namespace std;
struct ele{
	string tag;
	string id;
	int level;
}G[200]; 
string s1,s2;
vector<int>ans;
vector<int>tmp;//这个地方要分开写,否则CSP过不了 
vector<string>str;
int tot=0,lev=0,num=0;
void tknzr(){
  str.clear(); int pos=0;
  while(1){
    pos=s2.find(" ");
    if(pos==string::npos){
    	str.push_back(s2);
    	break;
    }
    str.push_back(s2.substr(0,pos));
    s2=s2.substr(pos+1);
  }
}
void search (){
   tmp.clear();
   for(int i=1;i<=tot;i++){
   	 while(!tmp.empty()&&G[i].level<=G[tmp.back()].level) num--, tmp.pop_back();
   	 if(G[i].id==str[num]||G[i].tag==str[num]) num++,tmp.push_back(i); 
		//这里若用参数区分就会错! 
   	 if(num==str.size()) ans.push_back(i),num--,tmp.pop_back();
   }
}
int main()
{
    int n,m;
//    freopen("in.txt","r",stdin);
	scanf("%d%d",&n,&m);
	getchar();
	for(int i=1;i<=n;i++) {
		s1.clear();
		getline(cin,s1);
		int j=0,cnt=0;
		string tag="",id=""; 
		for(;s1[j]=='.';j++) if(j%2==1) cnt++;
		for(;s1[j]!=' '&&j<s1.size();j++) tag+= s1[j]>='A'&&s1[j]<='Z'? tolower(s1[j]):s1[j];
		j++;//跳过空格 
		for(;j<s1.size();j++) id+=s1[j];
		G[++tot].tag=tag,G[tot].id=id,G[tot].level=cnt;
	}	
	for(int i=1;i<=m;i++){
		s2.clear(); 
		getline(cin,s2);
		ans.clear(); 
		if(s2.find(" ")==string::npos){
			if(s2[0]!='#'){
				for(int s=0;s<s2.size();s++) //将s2转为小写 
			       if(s2[s]>='A'&&s2[s]<='Z') s2[s]=tolower(s2[s]);
				for(int i=1;i<=tot;i++)
				   if(G[i].tag==s2) ans.push_back(i);
			}
			else if(s2[0]=='#'){
				for(int i=1;i<=tot;i++){
					if(G[i].id==s2) ans.push_back(i);
				}
			}
		}
		else{
			num=0; 		
			if(s2[0]!='#') {
			    for(int s=0;s<s2.size();s++) //将s2转为小写 
			       if(s2[s]>='A'&&s2[s]<='Z') s2[s]=tolower(s2[s]);
			}		
		    tknzr();
			search(); 
		}
		printf("%d",ans.size());
		sort(ans.begin(),ans.end());
		for(int i=0;i<ans.size();i++) printf(" %d",ans[i]);
		printf("\n");
	} 
	return 0;
} 

自下而上:

#include<bits/stdc++.h>
using namespace std;
struct ele{
	string tag;
	string id;
	int level;
}G[200]; 
string s1,s2;
vector<int>ans;
vector<int>tmp;//这个地方要分开写,否则CSP过不了 
vector<string>str;
int tot=0,num=0;
void tknzr(){
  str.clear(); int pos=0;
  while(1){
    pos=s2.find(" ");
    if(pos==string::npos){
    	str.push_back(s2);
    	break;
    }
    str.push_back(s2.substr(0,pos));
    s2=s2.substr(pos+1);
  }
  num = str.size(); 
}
int main()
{
    int n,m;
//    freopen("in.txt","r",stdin);
	scanf("%d%d",&n,&m);
	getchar();
	for(int i=1;i<=n;i++) {
		getline(cin,s1);
		int j=0,cnt=0;
		string tag="",id=""; 
		for(;s1[j]=='.';j++) if(j%2==1) cnt++;
		for(;s1[j]!=' '&&j<s1.size();j++) tag+= s1[j]>='A'&&s1[j]<='Z'? tolower(s1[j]):s1[j];
		j++;//跳过空格 
		for(;j<s1.size();j++) id+=s1[j];
		G[++tot].tag=tag,G[tot].id=id,G[tot].level=cnt;
	}	
	for(int i=1;i<=m;i++){
		getline(cin,s2);
		str.clear();
		ans.clear();
		if(s2[0]!='#'){//将s2转为小写 
			for(int s=0;s<s2.size();s++) 
			    if(s2[s]>='A'&&s2[s]<='Z') s2[s]=tolower(s2[s]);} 
		tknzr();//分词 				
		for(int j=n;j>=1;j--)
		{
			num=str.size()-1; 
			if(G[j].tag==str[num]||G[j].id==str[num]) //与最后一个token相等
			{
				tmp.clear();
				tmp.push_back(j);//记录的是高级的祖先 
				while(--num>=0) //考虑下一个token,其lev必须是在一个递减的序列里 
				{ 
				    int u=0;
				    for(int k=tmp.back();k>=1;k--)
                    {
                        if(G[k].level<G[tmp.back()].level) { 
                            tmp.push_back(k); 
                            if(G[k].tag==str[num]||G[k].id==str[num]){
                                u = k; break;
                            }
                        }
                    }
					if(G[u].tag!=str[num]&&G[u].id!=str[num]) break;
				}
				if(num<0) ans.push_back(j);
			}
		}								
		printf("%d",ans.size());
		sort(ans.begin(),ans.end());
		for(int i=0;i<ans.size();i++) printf(" %d",ans[i]);
		printf("\n");
	} 
	return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
图像识别技术在病虫害检测的应用是一个快速发展的领域,它结合了计算机视觉和机器学习算法来自动识别和分类植物上的病虫害。以下是这一技术的一些关键步骤和组成部分: 1. **数据收集**:首先需要收集大量的植物图像数据,这些数据包括健康植物的图像以及受不同病虫害影响的植物图像。 2. **图像预处理**:对收集到的图像进行处理,以提高后续分析的准确性。这可能包括调整亮度、对比度、去噪、裁剪、缩放等。 3. **特征提取**:从图像提取有助于识别病虫害的特征。这些特征可能包括颜色、纹理、形状、边缘等。 4. **模型训练**:使用机器学习算法(如支持向量机、随机森林、卷积神经网络等)来训练模型。训练过程,算法会学习如何根据提取的特征来识别不同的病虫害。 5. **模型验证和测试**:在独立的测试集上验证模型的性能,以确保其准确性和泛化能力。 6. **部署和应用**:将训练好的模型部署到实际的病虫害检测系统,可以是移动应用、网页服务或集成到智能农业设备。 7. **实时监测**:在实际应用,系统可以实时接收植物图像,并快速给出病虫害的检测结果。 8. **持续学习**:随着时间的推移,系统可以不断学习新的病虫害样本,以提高其识别能力。 9. **用户界面**:为了方便用户使用,通常会有一个用户友好的界面,显示检测结果,并提供进一步的指导或建议。 这项技术的优势在于它可以快速、准确地识别出病虫害,甚至在早期阶段就能发现问题,从而及时采取措施。此外,它还可以减少对化学农药的依赖,支持可持续农业发展。随着技术的不断进步,图像识别在病虫害检测的应用将越来越广泛。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值