问题描述:
解题思路:
50分错误思路:最初理解题目有偏差,而且样例能过,测试了很多数据,找不到原因,因为对于我的理解,我的代码没有问题,后来和同学对的时候才发现问题所在,我理解的是子代会继承父代元素,而样例里面偏偏避开了这一块,样例的测试数据都是无子代的,所以我的代码能过测试数据。实际上就是,对于输入的查询选择器,我会输出直接对应的元素及它的所有子代的行数,但实际上,AC的代码只会该对应元素行号,不会输出它的子代元素行号。举个例子,查询html,正确输出是1 1,但是我会输出所有行号。我感觉这是题目的bug(虽然我不知道是不是…),感觉题目没有讲清这一块,我理解的html代码父代和子代样式是有继承关系的。我错误的思路就是构造行元素的完整字符串,从根一直到该行的元素,以空格分离,查询的时候,只要查询的字符串都是该行的某个子字符串即可。(要求顺序一致)
100分思路:本题类似于构造树的思想,每一个元素结构体会记录父元素的索引。构造结构体yuansu:id字符串,label字符串,fa(父亲索引)。find(int q,int j)是判断ys[j]是否和qslen[q]匹配,如果不匹配,沿着路径找父元素判断find(q,ys[j].fa),一直到根或者查找成功。
以‘.’的个数来区别元素级数,不确定是否有多个0级元素,所以为了不进行额外判断,将所有元素的级数升一级,同时,cur数组记录了当前每级的最新行号,所以有如下代码:cur[(cot>>1)+1]=i;ys[i].fa=cur[cot>>1]。
关键:最后查询的时候,从qs字符串数组的最后一个字符串,即qs[qlen-1]开始往前查询,如果是id,则判断ys[j].id是否等于qs[qlen-1],如果不是,这个元素就不匹配,continue;如果是,cot++,调用递归函数find(q-1,j),注意这里还是在j号元素进行判断,因为下一个字符串qs[q-1]可能就是ys[j].label。如果是标签判断过程基本上和id一样,只是匹配的话应该调用函数find(q-1,j-1)。
bug点:注意>>和算术运算符的优先级:>>小于-。
实验代码:
#include<iostream>
#include<sstream>
using namespace std;
struct yuansu
{
string label;
string id;
int fa;
};
yuansu ys[110];
int cur[110],qslen,cot,n,anstol,ans[110];
string qs[222];
bool matching(string str1,string str2)
{
int len1 = str1.length();
int len2 = str2.length();
if (len1 != len2)
return false;
int d = 'a' - 'A';
for (int i = 0; i < len1; i++)
{
if (str1[i] == str2[i]) continue;
if (str1[i] == str2[i] + d) continue;
if (str1[i] == str2[i] - d) continue;
return false;
}
return true;
}
void find(int goal,int j)
{
if(goal==-1||j==0)
return;
if(qs[goal][0]=='#')
{
if(ys[j].id==qs[goal])
{
cot++;
find(goal-1,j);
}
else
find(goal,ys[j].fa);
}
else
{
if(matching(qs[goal],ys[j].label))
{
cot++;
find(goal-1,j-1);
}
else
find(goal,ys[j].fa);
}
}
int main(void)
{
int m;
string str;
cin>>n>>m;
getchar();
for(int i=1;i<=n;i++)
{
getline(cin,str);
cot = 0;
while (str[cot] == '.') {
cot++;
}
cur[(cot>>1)+1]=i;
ys[i].fa=cur[cot>>1];
if(str.find('#')!=string::npos)
{
ys[i].id=str.substr(str.find('#'));
ys[i].label=str.substr(cot,str.find('#')-cot-1);
}
else
{
ys[i].id="";
ys[i].label=str.substr(cot);
}
}
for(int i=0;i<m;i++)
{
getline(cin,str);
stringstream qsin(str);
qslen=0,anstol=0;
while(qsin>>qs[qslen]) {
qslen++;
}
for(int j=1;j<=n;j++)
{
cot=0;
int q=qslen-1;
if(qs[q][0]=='#')
{
if(ys[j].id!=qs[q])
continue;
cot++;
find(q-1,j);
}
else
{
if(!matching(ys[j].label,qs[q]))
continue;
cot++;
find(q-1,ys[j].fa);
}
if(cot==qslen)
ans[anstol++]=j;
}
cout<<anstol<<" ";
for(int k=0;k<anstol;k++)
cout<<ans[k]<<" ";
cout<<endl;
}
return 0;
}