CSP201809-3 元素選擇器(模擬)

題目

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

綜述

最近寫的模擬題總是寫的有點長,但是思路並不難理解,debug起來也簡單,可能是面向對象的原因吧;
在這裏插入圖片描述

思路

模擬題用面向對象的思想;
如下結構體,分別存儲某一個標籤的行、父標籤位置、層級、名字、id;
從解題的思想來看這個,是有贅餘了,的確。但是對於模擬題,特別是稍微複雜點的,將一些名詞對象的屬性什麼什麼的抽象出來,不混爲一談的話會簡單一點。

struct element{
	int row;
	int fa;
	int grade;
	string name;
	string id;
	element(){
		grade = 0;
		name = "";
		id = "";
	}
};

in()

in函數就是輸入,將輸入抽象到對應的結構體數組內,較爲簡單;

issame(string s1,string s2)

這個函數就是判斷兩個標籤是否相同,主要是大小寫不敏感的處理,較爲簡單;如果兩個字符的ASCll差的絕對值是32那麼相同;

find()

這個函數就是用於查找對應的標籤
抽象出來的思路如下所示:
(假設標籤和id都屬於label)
假設要查詢的爲 label1 label2 label3 …label n
(下面的數組名和代碼裏面的相同)

  • 找出倒數第二個標籤所有出現的位置存到數組 ans
  • 對ans數組裏面的位置進行判定,看是否能夠匹配查詢的1號到倒數第二個標籤,將可以的存到數組_ans
  • 從_ans第一個開始查詢看這一個分支裏面是否存在倒數第一個標籤label n;

坑點

第一遍是讀錯題意沒過,但是也還是過了7個點,也算可以。
第二遍一把過,也許,也許這時候體現出了面向對象編程的好處,即抽象程度高,易模擬,不易出些奇奇怪怪好幾天找不出的BUG;

注意

  • 在回溯的時候注意處理根節點以及label數組最後一個是否和根節點相等;
  • 看清題意,只需要找到所有分支裏面最靠前的且符合題意的即可;

其他的東西

第一次提交是今天上午,當時沒考慮後代中id和標籤的嵌套問題,只過了七個點,也沒有考慮標籤是大小寫不敏感的;
在這裏插入圖片描述

代碼

#include <iostream>
#include <cstring>
#include <vector> 
using namespace std;
int n,m;
struct element{
	int row;
	int fa;
	int grade;
	string name;
	string id;
	element(){
		grade = 0;
		name = "";
		id = "";
	}
};
vector<element> v;
vector<int> ans;
vector<int> subans;
void in(){
	getchar();
	for(int i=0;i<n;i++){
		element el;
		char ch;
		while(1){
			scanf("%c",&ch);
			if(ch==' ')continue;
			else if(ch=='.')el.grade++;
			else if(ch=='\n'){
				el.grade /= 2;
				break;
			}
			else if(ch=='#'){
				while(1){
					scanf("%c",&ch);
					if(ch=='\n'){
						el.grade /= 2;
						break;
					}
					el.id += ch; 
				}
				break;
			}
			else{
				el.name += ch;
			}
		}
		el.row = i+1;
		v.push_back(el); 
	}
	v[0].fa = -1;
	for(int i=1;i<n;i++){
		for(int j=i-1;j>=0;j--){
			if(v[j].grade < v[i].grade){
				v[i].fa = j;
				break;
			}
		}
	}
}
bool issame(string s1,string s2){
	if(s1.size() != s2.size())return false;
	for(int i=0;i<s1.size();i++){
        if(s1[i]==s2[i] || s1[i]==s2[i]+32 || s1[i]+32==s2[i]){
            continue;
        }else{
            return false;
        }
    }	
    return true;
}
void find(){
	vector<string> decend;
    string node;
    for(int k=0;k<m;k++){
        char ch;
        decend.clear();
        node.clear();
        ans.clear();
        v2.clear();
        subans.clear();
        while(1){
            scanf("%c",&ch);
            if(ch=='\n'){
                decend.push_back(node);
                break;
            }
            else if(ch==' '){
                decend.push_back(node);
                node.clear();
            }else node.push_back(ch);
        }
    //decend獲取
    if(decend.size()==1){
        if(decend[0][0]=='#'){
            string s = decend[0].substr(1,decend[0].size()-1);
            bool flag = false;
            for(int i=0;i<v.size();i++){
                if(v[i].id == s){
                    cout<<1<<" "<<v[i].row<<endl;
                    flag = true;
                    break;
                }
            }
            if(!flag)cout<<0<<endl;
        }
        else{
            for(int i=0;i<v.size();i++){
                if(issame(v[i].name,decend[0])){
                    ans.push_back(i);
                }
            }
            cout<<ans.size();
            for(int i=0;i<ans.size();i++){
                cout<<" "<<v[ans[i]].row;
            }
            cout<<endl;
        }
    }
	else{
		//找到倒數第二個標籤所有出現的位置
        string s = decend[decend.size()-2];
        
        if(s[0]=='#'){
            for(int i=0;i<v.size();i++){
                if(v[i].id == s.substr(1,s.size()-1)){
                    subans.push_back(i);
                }
            }
        }else{
            for(int i=0;i<v.size();i++){
                if(issame(v[i].name,s)){
                    subans.push_back(i);
                }
            }
        }
        vector<int> _ans;
        _ans.clear();
        //倒數第二個標籤進行判定
        for(int i=0;i<subans.size();i++){
            vector<string> subdecend;

            for(int j=0;j<decend.size()-1;j++)subdecend.push_back(decend[j]);
           
            int now = subans[i];
            bool flag = false;
            while(v[now].fa != -1){
                
                if(subdecend.size()==0){
                    flag = true;
                    break;
                }
                if(subdecend.back()[0]=='#' && subdecend.back().substr(1,subdecend.back().size()-1) == v[now].id ){
                    subdecend.pop_back();
                }
                else if(subdecend.back()[0] != '#' && issame(v[now].name,subdecend.back())){
                    subdecend.pop_back();
                }
                now = v[now].fa;
            }
            if(subdecend.size()==0 || flag){
                _ans.push_back(subans[i]);
                continue;
            }
            if(subdecend.size()>1)continue;

            if(subdecend.back()[0]=='#' && subdecend.back().substr(1,subdecend.back().size()-1)== v[now].id){
                _ans.push_back(subans[i]);continue;
            }
            if(subdecend.size()==1 && issame(subdecend.back(),v[now].name)){
                _ans.push_back(subans[i]);
                continue;
            }
        }
        bool flag = false;
        if(_ans.size()==0){
            cout<<0<<endl;
            continue;
        }
        //對所有分支進行查找
        for(int i=0;i<_ans.size();i++){
            if(flag)break;
            string s = decend.back();
            if(s[0]=='#'){
                //id
                for(int j=_ans[i]+1;j<v.size();j++){
                    if(v[j].grade <= v[_ans[i]].grade){
                        break;
                    }
                    if(v[j].id == s.substr(1,s.size()-1)){
                        ans.push_back(j);
                        flag = true;
                        break;
                    }
                }
            }else{
                //! id
                for(int j=_ans[i]+1;j<v.size();j++){
                    if(v[j].grade <= v[_ans[i]].grade){
                        break;
                    }
                    if(issame(v[j].name,s)){
                        ans.push_back(j);
                        flag = true;
                    }
                }
            }
        }
        cout<<ans.size();
        for(int i=0;i<ans.size();i++){
            cout<<" "<<v[ans[i]].row;
        }
        cout<<endl;
    }
    }
}
int main(){
	cin>>n>>m;
	in();
	find();
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章