最近公共祖先—单链表最近公共结点

LCA问题最简单的解法,转化成两个单链表,求最近交点。

OJ时WA,因为在查询(name1,name1)时,即使name1不在树中,但是也可知其公共祖先就是name1.



#include <stdio.h>
#include <cstring>
#include <string.h>

const int stringSize = 1024;
const int statusNum = 100*stringSize;
int count = 0;//已经输入的不同字符串的个数
int c = 0;//状态空间个数
int statusRecord[statusNum];
int status[statusNum][52];
int father[300];//编号为i的元素的父节点编号为father[i]
char name[300][stringSize];//编号为i的元素的名字


int add(){
++c;
statusRecord[c] = 0;
memset(status[c],0,sizeof(status[c]));
return c;
}


int find( char* s ){
int row=0,column=0;
char* ptr = s;


while( *ptr != '\0' ){
column = (*ptr-'Z')>0 ? *ptr-'a'+26 : *ptr-'A';
if( status[row][column]==0 )
status[row][column]=add();
row = status[row][column];
ptr++;
}


return statusRecord[row]>0 ? statusRecord[row] : statusRecord[row]=++count;
}


void insert( char* s1, char* s2 ){
int index1 = find(s1);
int index2 = find(s2);
father[index2] = index1;
strcpy(name[index2],s2);
if( father[index1]==0 ){
father[index1] = index1;
strcpy(name[index1],s1);
}
}


int findFather( int i, int& length ){
if( father[i]==0 )
return 0;
while( i!=father[i] ){
i = father[i];
length++;
}
return i;
}


int findNearestAncester( char* s1, char* s2 ){
int index1 = find(s1);
int index2 = find(s2);
int length1=0, length2=0;
int father1 = findFather(index1,length1);
int father2 = findFather(index2, length2);
if( father1!=father2 || father1==0 || father2==0 )
return -1;

while( length1>length2 ){
index1 = father[index1];
length1--;
}
while( length2>length1 ){
index2 = father[index2];
length2--;
}
while( index1!=index2 ){
index2 = father[index2];
index1 = father[index1];
}
return index1;
}


int main(){
memset(status[0],0,sizeof(status[0]));
memset(father,0,sizeof(father));
int N=0;
scanf("%d",&N);
char s1[stringSize], s2[stringSize];
for( int i=0; i<N; i++ ){
scanf("%s%s",s1,s2);
insert(s1,s2);
}
int M=0;
scanf("%d",&M);
for( int i=0; i<M; i++ ){
scanf("%s%s",s1,s2);
if( strcmp(s1,s2)==0 )
puts(s1);
else{
int fatherIndex = findNearestAncester(s1,s2);
if( fatherIndex==-1 )
puts("-1");
else
puts(name[fatherIndex]);
}
}
return 0;
}






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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值