题目描述
知识图谱是一种结构化的语义网络,用于描述物理世界中的概念及其实例的相关关系。可以把知识图谱看成是一种有向图,图中的点是概念或实例,图中的边是概念及其实例的相关关系。
现定义一种简单的知识图谱
概念:包括父概念及其子概念,通过subClassOf关系关联,父子概念可以有多个层级;
实例:仅和概念之间通过instanceOf关系关联:
关系:以三元组的形式表示,三元组是一个以空格为成员间分隔符的字符串。例如"student subClassOf person"表示student是person的子概念,“apple instanceOf fruit"表示apple是概念fruit的实例。
给定一个知识图谱,请编写一个方法,可以根据一个概念查找其所有的实例。如果一个概念拥有子概念,那么返回的结果需要包含其所有子概念的实例;如果输入的概念没有实例,则返回字符串"empty”(说明:输出字符串文本不需要包含引号)。
给定的图谱满足以下限制:
1、有向图中不存在环路
2、所有点和关系的定义对大小写敏感
输入描述:
输入第1行,表示图谱中关系的数量n,取值范围[1,10000]
从第2行到n+1行,表示图谱中的关系,每一行是一个关系三元组第n+2行,表示待查找的元节点,是关系三元组中存在的点。
每行字符的长度不超过100。
输出描述
按字典序升序排列的字符串数组,其内容是概念及其子概念的所有实例。
样例1
// 输入
3
student subClassOf person
Tom inslenceOf student
Marry instanceOf person
person
//输出
Marry Tom
解释
student是person的子概念,Tom是student的实例,Marry是person的
实例,Marry的字典序小于Tom,所以返回Marry Tom。
样例2
// 输入
1
apple instanceOf fruit
fruit
// 输出
apple
思路:
存储所有实例,和每一对父子关系,根据给出的概念,遍历所有实例,向上查找其节点是否是给出概念的子节点。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <set>
#include <unordered_set>
#include <unordered_map>
using namespace std;
int n;
string s1,s2,s3,ss;
unordered_map<string,string> p; // 存储每一对的父节点
unordered_set<string> k; // 存储所有实例下
set<string> res;
int main()
{
cin>>n;
for(int i=0;i<n;i++)
{
cin>>s1>>s2>>s3;
if(s2=="instanceOf") k.insert(s1);
p[s1]=s3;
}
cin>>ss;
for(auto s:k) // 遍历每个实例
{
string s1=s;
// 向上查找父节点
while(p.count(s1))
{
if(p[s1]==ss)
{
res.insert(s);
break;
}
s1=p[s1];
}
}
if(res.size()==0) puts("empty");
else
{
for(auto s:res) cout<<s<<" ";
}
return 0;
}