元素选择器 (CCF 2018-09 3)

一、题目
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
二、分析
题目比之前的CIDR合并好读很多,这题第一步同样也是处理输入,然后直接将三种选择的选择方法编写出来,依次选择即可。
1、输入
输入主要是n行HTML文档和m行元素选择器。对于HTML文档,每一行需要记录的信息有级别、元素以及属性。对于元素选择器,每一行需要记录的有种类,后代等级(对于后代选择器来说)以及选择器的具体内容。
清晰了输入的重点信息,就可以建立HTML的元素选择器的数据结构了,然后分别用两个链表存储它们,方便遍历。

class HtmlLine {
	int rank;
	String factor;
	String attribute;
	public HtmlLine(int rank,String factor,String attribute)
	{
		this.rank=rank;
		this.factor=factor;
		this.attribute=attribute;
	}
}
class Select {
	int kind;   //1:标签选择器		2:id选择器	3:后代选择器
	int c;   //后代选择器的等级,若是不是后代选择器,默认为0
	String s;
	public Select(int kind,int c,String s)
	{
		this.kind=kind;
		this.c=c;
		this.s=s;
	}
}

2.处理标签选择器和id选择器
这两类的处理过程十分类似,需要注意的就是,一个区分大小写,一个不区分大小写

3.处理后代选择器
这里题目其实已经提示了,对于除最后一级之外的,采用贪心策略,每一次选择HTML等级最小的对应行,然后后面的搜索从上一次行的下一行开始即可。

三、代码

package 元素选择器3;
/* 测试数据
输入:
11 5
html
..head
....title
..body
....h1
....p #subtitle
....div #main
......h2
......p #one
......div
........p #two
p
#subtitle
h3
div p
div div p

输出:
3 6 9 11
1 6
0
2 9 11
1 11
 */
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
class HtmlLine {
	int rank;
	String factor;
	String attribute;
	public HtmlLine(int rank,String factor,String attribute)
	{
		this.rank=rank;
		this.factor=factor;
		this.attribute=attribute;
	}
}
class Select {
	int kind;   //1:标签选择器		2:id选择器	3:后代选择器
	int c;   //后代选择器的等级,若是不是后代选择器,默认为0
	String s;
	public Select(int kind,int c,String s)
	{
		this.kind=kind;
		this.c=c;
		this.s=s;
	}
}
public class Main {
	static int n,m;
	static List<HtmlLine> html = new ArrayList<HtmlLine>();
	static List<Select> select = new ArrayList<Select>();
	
	private static void storehtml(String line)  //存储每一行HTML
	{
			int pnum = 0;
			boolean flag = false;
			String factor="";
			String attribute="#";
			for(int j=0;j<line.length();j++)
			{
				char pos = line.charAt(j);
				if(pos=='.')
					pnum++;
				else if(!flag&&pos!=' '&&pos!='#') 
					factor+=pos;
				else if(pos==' '||pos=='#') 
					flag=true;
				else if(flag)
					attribute+=pos;
				else continue;
			}
			html.add(new HtmlLine(pnum/2,factor,attribute));
	}
	private static void storeselect(String s)  //存储每一行元素选择器
	{
		int num=0;  //空格数量
		boolean flag = false;  //是否有#
		for(int j=0;j<s.length();j++)
		{
			char pos = s.charAt(j);
			if(pos==' ')
				num++;
			if(pos=='#')
				flag=true;
		}
		if(!flag&&num==0) //标签选择器
			select.add(new Select(1,0,s));
		else if(flag)  //id选择器
			select.add(new Select(2,0,s));
		else if(!flag&&num!=0) //后代选择器
			select.add(new Select(3,num+1,s));					
	}
	private static void labelSelect(String label)   //标签选择器,大小写不敏感
	{
		List<Integer> number = new ArrayList<Integer>();
		for(int i=0;i<n;i++)
			if(html.get(i).factor.equalsIgnoreCase(label))
				number.add(i+1);
		System.out.print(number.size()+" ");
		for(int i=0;i<number.size();i++)
			System.out.print(number.get(i)+" ");
		System.out.println("");
	}
	private static void idSelect(String id)  //id选择器,大小写敏感
	{
		List<Integer> number = new ArrayList<Integer>();
		for(int i=0;i<n;i++)
			if(html.get(i).attribute.equals(id))
				number.add(i+1);
		System.out.print(number.size()+" ");
		for(int i=0;i<number.size();i++)
			System.out.print(number.get(i)+" ");
		System.out.println("");
	}
	private static void offspringSelect(String o,int c)  //后代选择器,贪心策略
	{
		String[] str = o.split(" ");
		int start=0;
		for(int i=0;i<c-1;i++)
		{
			String l = str[i].trim();
			for(int j=start;j<n;j++)
			{
				if(html.get(j).factor.equalsIgnoreCase(l))
				{
					start=j+1;
					break;
				}
			}
		}
		List<Integer> number = new ArrayList<Integer>();
		for(int k=start;k<n;k++)
		{
			if(html.get(k).factor.equalsIgnoreCase(str[c-1]))
				number.add(k+1);
		}
		System.out.print(number.size()+" ");
		for(int i=0;i<number.size();i++)
			System.out.print(number.get(i)+" ");
		System.out.println("");
	}
	
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		n = in.nextInt();
		m = in.nextInt();
		in.nextLine();  //这里要换一下行,否则会读入一个空行
		for(int i=0;i<n;i++)
			storehtml(in.nextLine());
		for(int i=0;i<m;i++)
			storeselect(in.nextLine());
		for(int i=0;i<m;i++)
		{
			Select t = select.get(i);
			if(t.kind==1)  //标签选择器
				labelSelect(t.s);
			else if(t.kind==2)  //id选择器
				idSelect(t.s);
			else              //后代选择器
				offspringSelect(t.s,t.c);
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值