hdu 4409 Family Name List 金华赛区1010 (解题报告)

金华赛区区域赛最后一题,比赛完后就马上给A了 = =! 哎~~~

#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 30000 +5 ;
//46MS 13568K 3213 B 

//字典树+模拟,这题真心无语了,比赛时就被题意坑了,在c询问的时候,我考虑了a是b的
//父节点的情况,一直WA。。。那种情况是不要考虑的。 
int in[65],father[65];
char s1[65],s2[65];

struct node{
    int fa,sum;
    char name[65];
    vector<int> g;   
}q[N];

struct tree{
	int cnt,no;
	tree *a[27*3];
	tree(){//初始化
		cnt=0,no=0;
		memset(a,NULL,sizeof(a));
	}
}*h;

bool cmp(int a,int b){
     if(strcmp(q[a].name,q[b].name)>0) return false;
     else return true;
}

void prin(int i){
	int j;
    puts(q[i].name);
    if(q[i].sum){
        sort(q[i].g.begin(),q[i].g.end(),cmp);
        for(j=0;j<q[i].sum;j++){
            prin(q[i].g[j]);
        }
    }
}
int getid(char cc){
    if(cc>='0' && cc<='9') return cc-'0';
	else if(cc>='a' && cc<='z') return cc-'a'+10;
	else return cc-'A'+36;
}

void bd(tree *root,char *ss,int k){
	tree *p=root;
	int i=0,id;
	while(ss[i]){
		if(ss[i]=='.' || ss[i]==' '){i++;continue;}
		id=getid(ss[i]);
		if(p->a[id]==NULL) p->a[id]=new tree();
		//建立新的结构体指针
		p=p->a[id];
		p->cnt++;//每次经过都+1
		i++;
	}
	p->no=k;
}

int ask(char *ss,tree *p){
	int l=strlen(ss);
	int k=0;
	while(k<l){
		if(ss[k]=='.'|| ss[k]==' '){ k++; continue;}
		int id=getid(ss[k]);
		if(p->a[id]==NULL ) return 0;
		else p=p->a[id];
		k++;
	}
	return p->no;
}
int main()
{
    int n,m,i,j;
    while(scanf("%d",&n)!=EOF,n){
        for(i=0;i<62;i++) in[i]=-1;
        for(i=0;i<n;i++) {q[i].g.clear();q[i].sum=0;q[i].fa=0;}
        h=new tree();
		getchar();
        for(i=0;i<n;i++){	
            gets(q[i].name);//puts(q[i].name);
            int w=0;
            while(q[i].name[w]=='.') w++;
            bd(h,q[i].name,i);
            in[w]=i;
            if(i==0) q[i].fa=-1;
            else{
                 while(in[--w]==-1);
                 q[i].fa=in[w];
                 q[in[w]].g.push_back(i);
                 q[in[w]].sum++;
            }
        }
        scanf("%d",&m);
        int no1,no2,no3;
        char c;
        while(m--){
            getchar();
            scanf("%c",&c);//printf("%c ",c);
            if(c=='L') prin(0);
            else if(c=='b'){
                 scanf("%s",s1);//puts(s1);
                 no1=-1;
                 no1=ask(s1,h);
				 if(no1==0) puts("1");
				 else if(no1==-1) puts("0");
				 else printf("%d\n",q[q[no1].fa].sum);
            }
            else if(c=='c'){
                 scanf("%s%s",s1,s2);// puts(s1);puts(s2);
                 no1=ask(s1,h);
                 no2=ask(s2,h);//printf("%d %d\n",no1,no2);

				 j=0,no3=-1;
                 while(q[no1].fa!=-1){ father[j++]=q[no1].fa; no1=q[no1].fa;}
				 while(q[no2].fa!=-1){
				     for(i=0;i<j;i++){
                         if(q[no2].fa == father[i]){
                             no3=father[i];break;
					     }
					 }
				  	 if(no3!=-1)break;
                     no2=q[no2].fa;
				 }
				 //printf("%d\n",no3);
                 i=0;
                 while(q[no3].name[i]=='.')i++;
				 for(;i<strlen(q[no3].name);i++) printf("%c",q[no3].name[i]);
                 printf("\n");
            } 
        }  
    }  
    return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值