嗯,也是折騰了一上午的題啊…好菜啊…其實就是普通的邏輯題,數據範圍都很小根本不用擔心超,就是把查詢邏輯處理好久可以了
主要注意:
- 標籤大小寫不敏感,id大小寫敏感,會在一個測試點裏集中測試,只有這個沒注意能拿90分(我就在這卡了好久,直到看到一個人的答案才恍然大悟)
- 標籤和id是可以混合的,也就是可以 div #two p這樣,我不清楚爲什麼說後代選擇器A B均爲xxxbalabala的,但實際上數據是混合的
- 搜索的時候注意搜索的時候搜索到的標籤之間一定有父子關係,同級元素是不能匹配兩個搜索詞的。
using namespace std;
#include<cstdio>
#include<string>
#include<list>
#include<stack>
struct xml{//元素的數據結構
string name;
string id;
int parent;
int lid;
int level;
void show(){
printf("'%s' '%s' %d %d %d\n",name.c_str(),id.c_str(),parent,lid,level);
}
};
int judgeLevel(string &s)//根據前面的兩個點判斷級別,用於確定元素級別和父親元素
{
int i=0;
for(;i<s.size()&&s[i]=='.';i++){}
return i/2;
}
xml x[101];
bool search(list<string> &keys,int right){
//根據搜索關鍵詞和初始位置從後往前搜索是否存在元素,是和具體的循環體配合的,因此多加了最尾元素的判斷
//如果第一個就匹配不了,直接退出
list<string>::iterator cur = keys.end(),ini = keys.begin();//迭代器的應用
cur--;//end指向空,因此要--纔是尾元素
if((*cur)!=x[right].id && (*cur)!=x[right].name)
{
//判斷尾元素是否匹配,因爲外端方法是循環向前遍歷,如果從這裏貪心就會多匹配一些元素
return false;
}
cur--;
ini--;//begin指向的是第一個元素,cur遍歷到begin--時纔會
if(cur==ini)//如果迭代完了,說明全都匹配上了
{
return true;
}
right = x[right].parent;
while(right>=0)
{
if((*cur) == x[right].id || (*cur) == x[right].name)
{
cur--;
if(cur==ini)
{
return true;
}
}
right = x[right].parent;//指向父親,從父親那開始繼續匹配,這也是從尾往前匹配的原因,因爲一個元素只可能有一個爸爸
}
return false;
}
bool lower(string &a){
//可以替換到下面的方法實現減少代碼量
//但替換後悔增加耗時和空間,具體原理不清楚
//應該是方法傳參的細節,也就是如果能少嵌套方法就儘量少嵌套
for(int i = 0;i<a.size();i++)
{
if(a[i]>='A' && a[i]<='Z')
{
a[i] -= 'A'-'a';
}
}
}
int main(){
int n,m;
scanf("%d %d",&n,&m);
getchar();
stack<xml> level;
for(int i = 0;i<n;i++)
{
char cline[80];
scanf("%[^\n]", &cline);getchar();
string line = cline;
int llevel = judgeLevel(line);
int pos = line.find(' ');
xml cur;
if(pos!=-1)//有空格說明有標籤和id
{
cur.name = line.substr(llevel*2,pos-llevel*2);
for(int j = 0;j<cur.name.size();j++)//標籤大小寫不敏感
{
if(cur.name[j]>='A' && cur.name[j]<='Z')
{
cur.name[j]-= 'A'-'a';
}
}
cur.id = line.substr(pos+1,line.size()-pos);
}else//沒有說明..分級後是完整的標籤
{
cur.name = line.substr(llevel*2,pos-llevel*2);
for(int j = 0;j<cur.name.size();j++)
{
if(cur.name[j]>='A' && cur.name[j]<='Z')
{
cur.name[j]-= 'A'-'a';
}
}
cur.id = "";
}
cur.lid = i;
cur.level=llevel;
//分配父親,僅在這裏使用xml結構中的level屬性
//利用棧,棧的大小和級別剛好可以形成對應關係
if(llevel==level.size())
{
if(level.empty())
{
cur.parent = -1;
level.push(cur);
}else{
cur.parent = level.top().lid;
level.push(cur);
}
}else if(llevel<level.size()){
while(llevel != level.size())
{
level.pop();
}
if(level.empty())
{
cur.parent = -1;
level.push(cur);
}else{
cur.parent = level.top().lid;
level.push(cur);
}
}else{}//不可能大於
x[i] = cur;
}
//接收查詢詞並處理
for(int i = 0;i<m;i++)
{
list<string> keys;
list<int> res;
char ckey[80];
char split;
scanf("%s",ckey);
split = getchar();
string skey = ckey;
skey = ckey;
if(skey[0] != '#')
{
for(int j = 0;j<skey.size();j++)
{
if(skey[j]>='A' && skey[j]<='Z'){
skey[j] -= 'A'-'a';
}
}
}
keys.insert(keys.end(),skey);
while(split == ' ')//分隔符是空格說明還有下一個,否則會接收到換行符
{
scanf("%s",ckey);
skey = ckey;
if(skey[0] != '#')
{
for(int j = 0;j<skey.size();j++)
{
if(skey[j]>='A' && skey[j]<='Z'){
skey[j] -= 'A'-'a';
}
}
}
keys.insert(keys.end(),skey);
split = getchar();
}
//搜索
int num = 0;
int pos;
for(int k = n-1;k>=0;k--)
{
pos = search(keys,k);
if(pos)
{
res.insert(res.begin(),k+1);
num++;
}
}
//輸出
printf("%d ",num);
for(list<int>::iterator iter = res.begin(),next;iter!=res.end();iter++)
{
next = iter;
next++;
if(next != res.end())
{
printf("%d ",*iter);
}else
{
printf("%d",*iter);
}
}
printf("\n");
}
return 0;
}
2019年9月3日第二次刷,更好的代碼:
#include <bits/stdc++.h>
using namespace std;
struct css{
int index;
int parent;
int level;
string name;
string id;
}e[102];
bool equal(css &ae,string &s){
return ae.name == s || ae.id == s;
}
int n,m;
bool find(int cur,vector<string> &v){
int p = 0;
int i = cur;
while(i>=0){
if(equal(e[i],v[p])){
p++;
}else if(p == 0)//非常關鍵的一步判斷
{
return false;
}
i = e[i].parent;
if(p>v.size()-1) {
return true;
}
}
return false;
}
int main(){
scanf("%d %d",&n,&m);
stack<css> s;
char block[2000];
int level;
char split;
for(int i = 0;i<n;i++)
{
scanf("%*[.]%n",&level);
scanf("%s%c",block,&split);
for(int j = 0;block[j] != '\0';j++)
{
if(block[j]>='A' && block[j]<='Z'){
block[j] -= ('A'-'a');
}
}
level/=2;
e[i].index = i;
e[i].level = level;
e[i].name = block;
if(split == ' '){
scanf("%s%*c",block);
e[i].id = block;
}
while(!s.empty() && s.top().level>=e[i].level) {
s.pop();
}
if(level == 0){
e[i].parent = -1;
}else{
e[i].parent = s.top().index;
}
s.push(e[i]);
}
while(m--)
{
vector<string> v;
split = ' ';
while(split != '\n'){
scanf("%s%c",block,&split);
if(block[0] != '#'){
for(int j = 0;block[j] != '\0';j++)
{
if(block[j]>='A' && block[j]<='Z'){
block[j] -= ('A'-'a');
}
}
}
v.insert(v.begin(),block);
}
vector<int> res;
for(int i = n-1;i>=0;i--)
{
if(find(i,v)){
res.insert(res.begin(),i+1);
}
}
printf("%d ",res.size());
for(int i = 0;i<res.size();i++)
{
printf("%d ",res[i]);
}
printf("\n");
}
return 0;
}