原题链接:计算机软件能力认证考试系统
深度优先搜索,将每一个查询根据空格分割成若干子串,一级一级搜索,下一级行数比当前行数大,且等级比当前等级高(这里定义等级与'.’的个数成正比,等级高者为后代),当搜索完最后一级时,即找到了一个满足要求的答案。
#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#define N 110
using namespace std;
int n,m,ran[N];//ran[i]存储第i行的等级,等级越大辈分越小,等级可由'.'的个数确定
string str[N],ss;
set<int> ret;//存储查询结果
vector<string> s;//将查询内容按空格分隔开
void dfs(int st,int d,int r){//st为遍历起点;d为当前搜索的第几个字符串,与s中存储的子串一致,从0开始;r为上一个子串的等级
if(d==s.size()){//搜索完所有的子串
ret.insert(st-1);
return;
}
for(int i=st;i<=n&&ran[i]>r;i++){//剪枝:ran[i]>r,当前的等级必须大于上一等级
int p=str[i].find(s[d]);//查找是否存在第d个子串,下面判断搜索是否合理
if(p!=-1&&(p==0||str[i][p-1]==' '||str[i][p-1]=='.')&&(p+s[d].size()==str[i].size()||str[i][p+s[d].size()]==' ')){
dfs(i+1,d+1,ran[i]);//搜索下一个子串
}
}
}
int main()
{
cin>>n>>m;
getchar();
for(int i=1;i<=n;i++){
getline(cin,str[i]);
int p=str[i].find_first_not_of('.');
ran[i]=p/2;//存储等级
while(p!=str[i].size()&&str[i][p]!=' '){//标签对大小写不敏感,统一记为小写
str[i][p]=tolower(str[i][p]);
p++;
}
}
for(int i=1;i<=m;i++){
getline(cin,ss);
ret.clear();
s.clear();
ss+=' ';
int pre=-1,p;
while((p=ss.find(' ',pre+1))!=-1){//按空格分割开,便于一级一级搜索
string sub=ss.substr(pre+1,p-pre-1);
if(sub[0]!='#') //标签统一记为小写
transform(sub.begin(),sub.end(),sub.begin(),::tolower);
s.push_back(sub);
pre=p;
}
dfs(1,0,-1);//搜索
cout<<ret.size();
for(auto it=ret.begin();it!=ret.end();it++)
cout<<" "<<*it;
cout<<endl;
}
return 0;
}