人类学研究对于家族很感兴趣,于是研究人员搜集了一些家族的家谱进行研究。实验中,使用计算机处理家谱。为了实现这个目的,研究人员将家谱转换为文本文件。下面为家谱文本文件的实例:
John
Robert
Frank
Andrew
Nancy
David
家谱文本文件中,每一行包含一个人的名字。第一行中的名字是这个家族最早的祖先。家谱仅包含最早祖先的后代,而他们的丈夫或妻子不出现在家谱中。每个人的子女比父母多缩进2个空格。以上述家谱文本文件为例,John这个家族最早的祖先,他有两个子女Robert和Nancy,Robert有两个子女Frank和Andrew,Nancy只有一个子女David。
在实验中,研究人员还收集了家庭文件,并提取了家谱中有关两个人关系的陈述语句。下面为家谱中关系的陈述语句实例:
John is the parent of Robert
Robert is a sibling of Nancy
David is a descendant of Robert
研究人员需要判断每个陈述语句是真还是假,请编写程序帮助研究人员判断。
输入格式:
对于测试用例中的每句陈述语句,在一行中输出True,如果陈述为真,或False,如果陈述为假。
输入样例:
6 5
John
Robert
Frank
Andrew
Nancy
David
Robert is a child of John
Robert is an ancestor of Andrew
Robert is a sibling of Nancy
Nancy is the parent of Frank
John is a descendant of Andrew
输出样例:
True
True
True
False
False
代码如下:
#include<iostream>
#include<stdio.h>
#include<string>
#include<cstring>
using namespace std;
typedef struct BiTNode
{
string data;
int space;//标记该名字有几个缩进
int parent;//保存此元素父亲的下标
} BiTNode,*BiTree;
BiTNode* CreateTree(int Len)//将家族成员存到数组里
{
BiTNode* Tree=new BiTNode[Len];
string name,name1;//家族成员的名字
getchar();//读换行符
for(int i=0; i<Len; i++)
{
//由于一般的输入会自动忽略空格,故用getline()函数解决
getline(cin,name);
int j=0,num=0;//num为空格个数
while(name[j]==' ')
{
num++;
j++;
}
Tree[i].space=num;
for(; j<name.length(); j++)
Tree[i].data+=name[j];
if(i==0)
Tree[i].parent=-1;
else
{
if(Tree[i].space==Tree[i-1].space)//与上一个结点的父亲相同
Tree[i].parent=Tree[i-1].parent;
else if(Tree[i].space > Tree[i-1].space)//是上一个结点的孩子
Tree[i].parent=i-1;
else//缩进比上一个结点少,情况比较复杂
{
int t=Tree[i-1].parent;
int m=Tree[t].parent;
int p=(Tree[i].space-Tree[i-1].space)%2;
while(p--)
{
if(p==1)
break;
m=Tree[m].parent;
}
Tree[i].parent=m;
}
}
}
return Tree;
}
int FindPos(string s,int num)//找字符串中第num个单词的第一个字符出现的位置
{
int i,p=0;//p表示遍历过的空格的个数
for(i=0; i<s.length(); i++)
{
if(s[i]==' ')
p++;
if(p==num-1)
break;
}
return i;
}
void Judge(BiTNode *Tree,string &s1,string &s2,string &ss,int L2)//L2为树的长度
{
int i;
int pos1,pos2;//表示两个名字出现的位置
for(i=0; i<L2; i++)
{
if(Tree[i].data==s1)
{
pos1=i;
}
if(Tree[i].data==s2)
{
pos2=i;
}
}
if(ss=="child")
{
int t=Tree[pos1].parent;
if(t!=-1)
{
if(Tree[t].data==s2)
cout<<"True"<<endl;
else
cout<<"False"<<endl;
}
else
{
if(Tree[pos1].space-Tree[pos2].space==2)
cout<<"True"<<endl;
else
cout<<"False"<<endl;
}
}
else if(ss=="ancestor")//缩进小的为祖先
{
if(Tree[pos1].space<Tree[pos2].space)
cout<<"True"<<endl;
else
cout<<"False"<<endl;
}
else if(ss=="sibling")//缩进一样为兄弟
{
if(Tree[pos1].space==Tree[pos2].space)
cout<<"True"<<endl;
else
cout<<"False"<<endl;
}
else if(ss=="parent")
{
int t=Tree[pos2].parent;
if(t!=-1)
{
if(Tree[t].data==s1)
cout<<"True"<<endl;
else
cout<<"False"<<endl;
}
else
cout<<"False"<<endl;
}
else if(ss=="descendant")//缩进大的为后代
{
if(Tree[pos1].space>Tree[pos2].space)
cout<<"True"<<endl;
else
cout<<"False"<<endl;
}
}
void InputState(BiTNode *Tree,string &s1,string &s2,string &ss,int L1,int L2)//输入若干陈述句,并提取需要的信息
{
int i,j;
int k1=0,k2=0,k3=0;
string s;//输入的陈述句
for(i=0; i<L1; i++)
{
j=0;
getline(cin,s);
while(s[j]!=' ')//提取第一个名字
{
s1 += s[j];
j++;
}
j=FindPos(s,6);
while(s[j]!='\0')//提取第二个名字
{
if(s[j]!=' ')
s2 += s[j];
j++;
}
j=FindPos(s,4)+1;
while(s[j]!=' ')//提取关系名词
{
ss += s[j];
j++;
}
/*Judge*/
Judge(Tree,s1,s2,ss,L2);
s1="";
s2="";
ss="";
}
}
int main()
{
int N,M;
BiTNode *T;
cin>>N>>M;
T=CreateTree(N);
string str1,str2,str;
InputState(T,str1,str2,str,M,N);
//Judge(T,str1,str2,str,N,M);
return 0;
}