题意:给定两个搜索序列,0表示向新结点搜索,1表示回溯。问两个序列表示的树是否同构?
思路:<法一>求出序列表示的树的所有节点的深度以及儿子数,最后排序,如果全部相同,则说明这两棵树同构。
<法二>将两个串都转化为树的最小表示之后比较是否相同。方法是先从树根开始找出所有子树,然后递归的找下去。同一层的按照字典序排序。比如对于010011两个分支分别为01和0011,0011只有一个分支(也即已经排好序),然后将01和0011按照字典序排序得到最小表示为:001101
#include <stdio.h>
#include <string.h>
//#include <stdlib.h>
#define N 3005
char s[N],t[N];
struct node{
int depth,son;
}a[N],b[N];//储存两棵树的深度和儿子数量
int T,stack[N][2],top;
int cmp(const struct node *a,const struct node *b){
if((*a).depth == (*b).depth)
return (*a).son - (*b).son;
return (*a).depth - (*b).depth;
}
void update(char x[N],struct node y[N]){
int i,j;
top = -1;
memset(stack,0,sizeof(stack));
stack[++top][0] = 0;
y[0].depth = 0;//0号节点保存根节点,深度为0
for(i = j = 0;x[i]!='\0';i++){
if(x[i] == '0'){//新结点进栈
stack[++top][0] = ++j;
y[j].depth = top;//结点的深度就是入栈时栈的深度
}else{
stack[top-1][1] += stack[top][1]+1;//更新儿子数量,只在当前节点退栈的时候更新其父亲
y[stack[top][0]].son = stack[top][1];//当前退栈节点的儿子数量保存到结构体
stack[top--][1] = 0;//及时将儿子数量清零
}
}
y[0].son = stack[0][1];
}
int main(){
freopen("a.txt","r",stdin);
scanf("%d",&T);
while(T--){
int i,len;
scanf("%s %s",s,t);
len = strlen(s)/2+1;
update(s,a);
update(t,b);
qsort(a,len,sizeof(struct node),cmp);
qsort(b,len,sizeof(struct node),cmp);
for(i = 0;i<len;i++)
if(a[i].depth!=b[i].depth || a[i].son!=b[i].son)
break;
if(i >= len)
printf("same\n");
else
printf("different\n");
}
}