題目
綜述
最近寫的模擬題總是寫的有點長,但是思路並不難理解,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();
}